使用 async / await
, 搭配 promise
, 可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性.
1.async
在函数前面加上async关键字可以定义一个 异步函数, 语法为:
async function name([param[, param[, ... param]]]) { statements }
例:
async function timeout() { return 'hello world' } timeout(); console.log('虽然在后面,但是我先执行');
打开浏览器控制台:
async 函数 timeout 调用了,但是没有任何输出,它不是应该返回 'hello world', 先不要着急, 看一看timeout()执行返回了什么? 把上面的 timeout() 语句改为console.log(timeout())
async function timeout() { return 'hello world' } console.log(timeout()); console.log('虽然在后面,但是我先执行');
控制台:
原来async 函数返回的是一个promise 对象,如果要获取到promise 返回值,我们应该用then 方法, 继续修改代码:
async function timeout() { return 'hello world' } timeout().then(result => { console.log(result); }) console.log('虽然在后面,但是我先执行');
控制台:
如果timeout 函数内部抛出错误呢? 那么就会调用Promise.reject() 返回一个promise 对象, 这时修改一下timeout 函数:
async function timeout(flag) { if (flag) { return 'hello world' } else { throw 'my god, failure' } } console.log(timeout(true)) // 调用Promise.resolve() 返回promise 对象。 console.log(timeout(false)); // 调用Promise.reject() 返回promise 对象。
控制台:
如果函数内部抛出错误, promise 对象有一个catch 方法进行捕获:
timeout(false).catch(err => { console.log(err) })
2.await
await
操作符用于等待一个 Promise
对象, 它只能在异步函数 async function
内部使用.
await
的使用语法非常简单:
[return_value] = await expression;
其中 expression
是一个 Promise
对象或者任何要等待的值;
而 await expression 的执行结果有以下几种情况:
- 若 expression 是一个 Promise 对象, 并且其以值 x 被 fulfilled, 则返回值为 x.
- 若 expression 是一个 Promise 对象, 并且其以异常 e 被 rejected, 则抛出异常 e.
- 若 expression 不是 Promise 对象, 则会将 expression 处理成一个以 expression 值被 fulfilled 的 Promise 对象, 然后返回这个 Promise 对象的最终值 (即 expression 值).( 这种用法没太大意义, 因此实际使用时还是尽量在 await 后跟一个 Promise 对象.)
另外需要注意的是, await
在等待 Promise 对象时会导致 async function
暂停执行, 一直到 Promise 对象决议之后才会 async function
继续执行.
async function foo() { var a = await new Promise((resolve) => { setTimeout(() => { resolve(1); }, 2000); }); console.log(a); // 第2秒时输出: 1 try { var b = await new Promise((resolve, reject) => { setTimeout(() => { reject(2); }, 1000); }) } catch (e) { console.log(e); // 第3秒时输出: 2 } // 函数暂停2秒后再继续执行 var sleep = await new Promise((resolve) => { setTimeout(() => { resolve('sleep'); }, 2000); }); var c = await 3; console.log(c); // 第5秒时输出: 3 } foo();