深入分析promise、async和await之执行顺序

let promise = new Promise( function( resolve, reject){
console. log( '进入promise')
//做一些异步操作
setTimeout( function(){
console. log( '执行完成');
resolve( '随便什么数据');
}, 2000);
});
promise. then( v => console. log( v));

console.log('..........')

运行结果:

进入promise
..........
执行完成
随便什么数据

生成promise对象后,开始执行函数体内的代码,当遇到setTimeout异步函数后,主线程将该异步函数对应的promise放入任务队列,并返回执行主程序console代码,执行完后再回去

从队列中取出setTimeout的promise任务,执行完后返回

promise、async和await之执行顺序:


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')

求打印结果是什么?

相信是个前端都知道啦,这道题目考的就是js里面的事件循环和回调队列咯~
今天题主假设看客都已经了解了setTimeout是宏任务会在最后执行的前提(因为它不是今天要讨论的重点),我们主要来讲讲promiseasyncawait之间的关系。

先上正确答案:

script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout

事实上,没有在控制台执行打印之前,我觉得它应该是这样输出的:

script start
async1 start
async2
async1 end
promise1
script end
promise2
setTimeout

为什么这样认为呢?因为我们(粗浅地)知道await之后的语句会等await表达式中的函数执行完得到结果后,才会继续执行。

MDN是这样描述await的:

async 函数中可能会有 await 表达式,这会使 async 函数暂停执行,等待表达式中的 Promise 解析完成后继续执行 async 函数并返回解决结果。

会认为输出结果是以上的样子,是因为没有真正理解这句话的含义。

阮一峰老师的解释我觉得更容易理解:

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

对啦就是这样,MDN描述的暂停执行,实际上是让出了线程(跳出async函数体)然后继续执行后面的脚本的。这样一来我们就明白了,所以我们再看看上面那道题,按照这样描述那么他的输出结果就应该是:

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

好像哪里不太对?对比控制台输出的正确结果,咦~有两句输出是不一样的呀!!

async1 end
promise2

为什么会这样呢?这也是这道题目最难理解的一个地方。要搞明白这个事情,我们需要先来回顾一些概念:

async

async function 声明将定义一个返回 AsyncFunction 对象的异步函数。

当调用一个 async 函数时,会返回一个 Promise 对象。当这个 async 函数返回一个值时,Promise 的 resolve 方法会负责传递这个值;当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。

所以你现在知道咯,使用 async 定义的函数,当它被调用时,它返回的其实是一个Promise对象。

我们再来看看 await 表达式执行会返回什么值。

await

语法:[return_value] = await expression;

表达式(express):一个 Promise 对象或者任何要等待的值。

返回值(return_value):返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。

所以,当await操作符后面的表达式是一个Promise的时候,它的返回值,实际上就是Promise的回调函数resolve的参数。

明白了这两个事情后,我还要再啰嗦两句。我们都知道Promise是一个立即执行函数,但是他的成功(或失败:reject)的回调函数resolve却是一个异步执行的回调。当执行到resolve()时,这个任务会被放入到回调队列中,等待调用栈有空闲时事件循环再来取走它。

终于进入正文:解题

好了铺垫完这些概念,我们回过头看上面那道题目困惑的那两句关键的地方(建议一边对着题目一边看解析我怕我讲的太快你跟不上啊哈哈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值