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

发布于 2022-09-12 02:35:01 字数 943 浏览 24 评论 0

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 语句的时候被加入到微任务队列的。到底哪一种说法是正确的呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冰雪梦之恋 2022-09-19 02:35:01

都没问题。

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

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

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

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

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

¢蛋碎的人ぎ生 2022-09-19 02:35:01

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

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

总结起来就是 reslove -> then

好听的两个字的网名 2022-09-19 02:35:01

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

再结合一个例子看下:

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。

泅渡 2022-09-19 02:35:01

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文