今天看到了一段代码
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
})
console.log('script end');
看到输出,才发现自己对async/await了解还不够,对于其与prominodese的区别还需要进一步进行研究
node.js
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
chrome console
1. async/await的一些基本概念
- async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)
- async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果
- async 返回一个Promise对象,可以使用
then
方法添加回调函数,当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句 - async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖
- async函数内部return语句返回的值,会成为then方法回调函数的参数
- async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到
- async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误,也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数
- 正常情况下,await命令后面是一个 Promise 对象,它的返回值,实际上就是Promise的回调函数的resolve的参数。如果不是 Promise 对象,就直接返回对应的值
- 若await命令后面是一个thenable对象(即定义了then方法的对象),那么await会将其等同于 Promise 对象
- 任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。
- 如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject
- 为了防止出错,最好把await命令放在try…catch代码块中
2、关于上面那段代码输出的解释
- 打印script start
- 执行async1(),打印async1 start
- 执行await async2(),async2()也是async定义的函数,打印async2,同时async2()返回一个promise对象
- 上一步async2()返回的promise对象会立即执行,遇到resolve,放入任务队列等待执行
- 执行new Promise,立即执行,打印promise1,其resolve()放入队列中等待执行
- 打印script end
- 执行第4步放入任务队列的resolve回调,因为async2()没有返回值,所以该resolve参数为undefined,什么也不打印
- 此时await等待的promise对象已经有了结果,可以继续执行async1函数后面的任务,打印async1 end
- 取出第5步放入任务队列的reslove回调,打印promise2
- 最后打印setTimeout
参考:promise、async和await之执行顺序的那点事,但是对于async1 end和promise2的顺序,作者的解释我存在一点疑惑,既然promise对象是立即执行的,那async返回的promise对象也会理解执行,直接到resolve函数,然后放入任务队列,根据我的打印结果,好像更容易让我理解,这里先留存一点疑问吧,整体的思路作者讲的很好。
2、async/awiat和promise之间的区别
- 它们的主要区别在于处理then链,使用Async/Await明显节约了不少代码。我们不需要写.then,不需要写匿名函数处理Promise的resolve值
- Async/Await可以通过try…catch来同时处理同步和异步错误,(还有点没理清楚)但在promise中,try…catch不能处理内部promise的异步错误
参考:js异步回调Async/Await与Promise区别