问答

promise then 的回调函数是在什么时候进入微任务队列的?

作者:admin 2021-08-21 我要评论

promise then 的回调函数是在遇到 resolve 语句的时候就被加入微任务队列,还是在遇到 then 语句的时候被加入到微任务队列? 在网上查了一些资料,发现有不同的...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

promise then 的回调函数是在遇到 resolve 语句的时候就被加入微任务队列,还是在遇到 then 语句的时候被加入到微任务队列?
在网上查了一些资料,发现有不同的说法:

  1. 比如在《深入理解ES6》中文版 244 页里是这么说的:“调用 resolve( ) 后会触发一个异步操作, 传入 then( ) 和 catch( ) 方法的函数会被添加到任务队列中并异步执行”,所以 then 方法的回调应该是在调用 resolve 后就被加入到队列中的?
  2. 对应的英文版原文是这么说的:“Calling resolve() triggers an asynchronous operation. Functions passed to then() and catch() are executed asynchronously, because these are also added to the job queue”
  3. 这个是知乎的回答:链接
  4. 这个是 StackOverflow 类似问题的回答:链接 ,答主在分析 event loop 的时候有这么一句:“The first then hooks up the first fulfillment handler, queuing a PromiseJobs job because the promise is already fulfilled”

1、2 都认为 then 的回调函数是在遇到 resolve 语句的时候就被加入微任务队列,3、4 都认为是在遇到 then 语句的时候被加入到微任务队列的。到底哪一种说法是正确的呢?

###

都没问题。

关键在于,then 是在 resolve 之前被调用的,还是 resolve 之后呢?

thenresolve 之前,then 不会加微任务,而是缓存起来,resolve 看到缓存里又 then 的回调,于是加微任务。

resolvethen 之前,resolve 的时候还没有任何回调要执行,自然不会加微任务。then 的时候发现已经 fullfilled ,于是直接加微任务。

也就是说,他们都有可能加,也都有可能不加,就看调用时的 promise 的状态了。

你的引用有些只说明了其一,但是说明里条件写得还是很清楚的,比如 4 里 "because the promise is already fulfilled"

###

发表下我的意见,在我的理解里,Promise 的实现中,then 只会把回调放到一个数组里保存,所以我认为,reslove 后,才会进入微任务队列,存放callback 只是一个存放的操作

当然 如果then的运行还没执行的时候,promise 已经reslove 了 ,我觉得会是同步的去把callback放入 microtasks的。

总结起来就是 reslove -> then

###

执行一个宏任务,过程中遇到微任务时,将其放到微任务的事件队列里,当前宏任务执行完成后,会查看微任务的事件队列,依次执行里面的微任务。如果还有宏任务的话,再重新开启宏任务……

再结合一个例子看下:

setTimeout(function?()?{
    console.log('a')
});


new Promise(function?(resolve)?{
    console.log('b');

    for?(var?i?= 0;?i?< 10000;?i++)?{
        i?== 99 && resolve();
    }
    
}).then(function?()?{
    console.log('c')
});

console.log('d');

//?b 
//?d
//?c
//?a

1.首先执行script下的宏任务,遇到setTimeout,将其放入宏任务的队列里。

2.遇到Promisenew Promise直接执行,打印b。

3.遇到then方法,是微任务,将其放到微任务的队列里。

4.遇到console.log('d'),直接打印。

5.本轮宏任务执行完毕,查看微任务,发现then方法里的函数,打印c。

6.本轮event loop全部完成。

7.下一轮循环,先执行宏任务,发现宏任务队列中有一个setTimeout,打印a。

###

发现老贺有答案了,比较喜欢这种讲事实摆依据的

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 使用箭头函数return数据不能实现

    使用箭头函数return数据不能实现

  • 个人小程序号能接入小程序3D地图吗?

    个人小程序号能接入小程序3D地图吗?

  • vue 移动端项目中,使用了better-scrol

    vue 移动端项目中,使用了better-scrol

  • css如何做出区域平均划分为四列

    css如何做出区域平均划分为四列

腾讯云代理商
海外云服务器