promise.then, setTimeout,await执行顺序问题

Posted billyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了promise.then, setTimeout,await执行顺序问题相关的知识,希望对你有一定的参考价值。

  •  promise.then VS setTimeout

技术分享图片

  在chrome和node环境环境中均输出2, 3, 1, 先输出2没什么好说的,3和1顺序让人有些意外

原因

有一个事件循环,但是任务队列可以有多个。

整个script代码,放在了macrotask queue中,setTimeout也放入macrotask queue。

但是,promise.then放到了另一个任务队列microtask queue中。

这两个任务队列执行顺序如下,取1个macrotask queue中的task,执行之。

然后把所有microtask queue顺序执行完,再取macrotask queue中的下一个任务。

代码开始执行时,所有这些代码在macrotask queue中,取出来执行之。

后面遇到了setTimeout,又加入到macrotask queue中,

然后,遇到了promise.then,放入到了另一个队列microtask queue。

等整个execution context stack执行完后,

下一步该取的是microtask queue中的任务了。

因此promise.then的回调比setTimeout先执行。

 

  • await

async function a() {
    await console.log(1)
    console.log(2)
}

async function b() {
    await a();
}

b();

console.log(3)

输出: 1, 3, 2

async function a() {
    await console.log(1)
    console.log(2)
}

async function b() {
    await a();
}

b();

setTimeont(function(){console.log(3)},0)
输出: 1,  2, 3

await不会造成程序阻塞,只是promise的语法糖,可以看看babel编译后async/await, 可以这么理解,async 是多个异步操作的promise对象,await相当于then,代码执行跟你用callback写的代码并没有什么区别,本质上并不是同步代码,只是让你思考代码逻辑的时候能够以同步的思维去思考,避开回调地狱,要理解异步,首先要理解cpu的工作方式,cpu执行代码的时候,一个周期是以时间片为单位,实际上,无论是php还是node,处理同一个请求,cpu需要的计算量是一样的,在同样的时间内,cpu能做的计算量是一样的,差别在于,node只是提高了cpu的利用率。从而提高了同一时间能处理的请求数量。
 
打个比方,你去银行办理业务,只有一个窗口在办理业务(一个cpu进程),假设有两个人(A和B)要办理银行卡(可理解为一次请求),方式一:A到窗口前,但这个时候要办卡的话,柜员告诉你,要你的身份证复印件(可理解为IO操作),这个时候,你去复印,柜员等待,回来后继续办理,A办理完成后,B接着同样的步骤。方式二:在A去复印身份证的时候,柜员受理B的办理请求, 等A回来后再受理A的业务。所以,很明显,方式二在同样多的时间内,一个窗口能办理的银行卡数量更多,因为这种方式充分利用了柜员等待的时间,那么方式一就是php处理请求的方式,在PHP中,处理IO操作的时候(比如,访问数据库,读取文件等),实际上cpu是处于等待状态,但其他资源此时得不到cpu的计算资源,属于资源浪费,cpu并没有接受下一个请求,而方式二,则是node处理的方式。所以综上所述,async/await 并不会影响node的并发数量,async/await是以同步的思维去写异步的代码。

 

 





























以上是关于promise.then, setTimeout,await执行顺序问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Promise.then 中访问范围外的变量(类似于闭包)

杂项2018-6-8

前端基础 | JS异步执行机制——事件循环(Event Loop)

Promise和RxJS处理异步对比

promise和Rxjs的一点区别

JS事件循环机制(宏任务,微任务)