promise then 的回调函数是在遇到 resolve 语句的时候就被加入微任务队列,还是在遇到 then 语句的时候被加入到微任务队列?
在网上查了一些资料,发现有不同的说法:
- 比如在《深入理解ES6》中文版 244 页里是这么说的:“调用 resolve( ) 后会触发一个异步操作, 传入 then( ) 和 catch( ) 方法的函数会被添加到任务队列中并异步执行”,所以 then 方法的回调应该是在调用 resolve 后就被加入到队列中的?
- 对应的英文版原文是这么说的:“Calling resolve() triggers an asynchronous operation. Functions passed to then() and catch() are executed asynchronously, because these are also added to the job queue”
- 这个是知乎的回答:链接
- 这个是 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
之后呢?
then
在 resolve
之前,then
不会加微任务,而是缓存起来,resolve
看到缓存里又 then
的回调,于是加微任务。
resolve
在 then
之前,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.遇到Promise
,new Promise
直接执行,打印b。
3.遇到then
方法,是微任务,将其放到微任务的队列里。
4.遇到console.log('d')
,直接打印。
5.本轮宏任务执行完毕,查看微任务,发现then
方法里的函数,打印c。
6.本轮event loop
全部完成。
7.下一轮循环,先执行宏任务,发现宏任务队列中有一个setTimeout
,打印a。
发现老贺有答案了,比较喜欢这种讲事实摆依据的