首页 > 解决方案 > Promise.prototype.then 链在调用堆栈、WebAPI 部分和微任务队列方面会发生什么?

问题描述

我想知道这个代码片段中.then关于堆栈、WebAPI 部分和微任务队列的 s 链发生了什么。我在Loupe中尝试过,但似乎没有注册.thens。

setTimeout(function() {console.log(2)}, 0);

Promise.resolve(1)
.then((value) => {console.log(value)}) //
.then((value) => {console.log(value)}) //

事实上,.thens 必须等到前一个.then返回一个已解决的承诺(.then链接),这让我感到困惑。我不确定这看起来如何。我的猜测是:

脚本第一次(也是唯一一次)运行时,它会识别.then为返回承诺的异步函数 - 所以它在 WebAPI 部分中执行此操作。第一个.thentake ( Promise.resolve1) 的承诺是同步的,并且会立即解决,因此.then的回调 ( (value) => {console.log(value)}) 会立即放入微任务队列中。也许脚本看到有一个.then链条并留下其余部分,因为它们都相互依赖。

没有什么可看的了,'main'/脚本从堆栈中弹出。现在,一直在微任务队列中等待的回调被压入堆栈并执行。太好了,回调记录 5 并且回调帮助第一个.then返回已履行的承诺,undefined并将其作为“结果”。第二个.then立即被要求接受这个新的承诺。我将在这里停下来,因为我没有信心。

对调用堆栈、WebAPI“线程”或“区域”以及微堆栈队列进行分步说明会很棒。

标签: javascript

解决方案


回调帮助第一个.then返回一个履行的承诺undefined作为它的“结果”。第二个.then立即被要求接受这个新的承诺。

不,.then(…)这两个方法都在主脚本的初始执行期间被调用,并且都立即返回一个新的 Promise(但尚未解决)。Promise 只是一个普通对象,可以像任何其他值一样传递和记录,脚本正常执行方法调用。

除了返回新的Promise 之外,.then(…)调用所做的是将回调注册为原始 Promise 上的履行/拒绝处理程序 - 而不执行它们。(当承诺已经实现时,就像您给出的示例一样,它还会立即安排处理程序运行,将它们放入微任务队列中)。

在微任务上执行第一个处理程序并记录数字后,它的返回值用于解析.then()已返回的承诺。在该承诺上注册的任何处理程序都将被安排运行。因此,当第一个微任务完成时,第二个微任务已经在队列中等待并使用结果值执行第二个处理程序,使其成为 log undefined,然后解决链中的最后一个承诺 - 但没有更多的处理程序可以调度,微任务队列将为空。


推荐阅读