我正试图深入研究承诺和事件循环,以加强我对它们的理解,这是我刚刚编写的代码(完全无用,不实用):
let a = Promise.resolve('Hello everyone!')
a.then(function first(x) {console.log(x); return x})
.then(function second(x) {console.log(x); return x})
.then(function third(x) {console.log(x); return x})
.then(function fourth(x) {console.log(x); return x})
.then(function fifth(x) {console.log(x); return x})
.then(function sixth(x) {console.log(x); return x})
.then(function seventh(x) {console.log(x); return x})
.then(function eighth(x) {console.log(x); return x})
let b = Promise.resolve(true);
b.catch(function bFirstThen(x) {console.log(x)})
.finally(function bFinally() {console.log('Its done')})
.then(function bThen(x){ console.log('The value is:', x)})
这将在控制台中打印以下内容:
Hello everyone!
Hello everyone!
Its done
Hello everyone!
Hello everyone!
Hello everyone!
The value is: true
Hello everyone!
Hello everyone!
Hello everyone!
但是,当我编写代码时,我希望它能够打印:
hello everyone;
hello everyone;
Its done
hello everyone;
The value is: true
hello everyone;
hello everyone;
hello everyone;
hello everyone;
hello everyone;
因为这就是我期望代码工作的方式:
我们的代码(在第一个勾号中)将同步运行,遍历每一行,如果以后有任何任务要运行,我们将把它们放在微任务队列中,以便在所有同步代码完成后稍后执行!
在第一行中,我们创建并立即解析一个promise,这样我们就知道了a中的任何函数。然后(在我们的情况下,它是唯一的一个)将立即放在微任务队列中,以便稍后执行!
我们找到了这行代码“x=>{console.log(x);return x}“由于我们的承诺已经得到了解决,这个任务将被放入我们的微任务队列中,以便以后执行,并且还将返回一个待定的承诺!现在,我们的微任务队列看起来类似于这个微任务队列=[function first(x){console.log(x);返回x}]
然后我们有7个。然后在引擎盖下,在hidden promise的名为OnMet的数组中设置这些函数。由于承诺没有得到解决,它们的处理程序还不会被放到微任务上,所以在同步代码之后,我们的微任务队列仍然只有一个任务要运行。
在我们的示例中,接下来的两行有意义的语句是“let b=promise.resolve(true);”和“b.catch(x=>{console.log(x)}”
请注意,我们的承诺已经解决,但是,我们正在做。抓住而不是。然后!很确定这是你一直想要避免的事情,但是现在,举例来说,让我们同意这一点!
在所有的同步代码之后,这就是我们的微任务队列的样子:microtaskqueue=[function first(x){console.log(x);返回x},函数bfirstthen(x){console.log(x)}]8。我们所有的同步代码都完成了,这意味着现在它将开始从微任务队列中获取任务并开始逐个运行任务,如果我们点击任何注册另一个微任务队列的代码,我们将!
这是我们从微任务队列运行的第一个函数“functionfirst(x){console.log(x);return x}“这被推送到调用堆栈中,当运行时,它会打印“hello everyone!”返回x,表示“大家好!”一旦这段代码完成,它将注册另一个任务,因此现在我们的微任务队列如下所示:微任务队列=[函数bfirstthen(x){console.log(x)},函数second(x){console.log(x);返回x}]
我们再次从微任务队列(恰好是这个函数:函数bfirstthen(x){console.log(x)})中获取第一个任务,并将其放在调用堆栈上运行!由于我们从.catch方法获得此处理程序,并且我们的承诺已解决(未被拒绝),因此此函数不运行,而.catch承诺现在被评估为已解决的承诺!
一旦它这样做了,我们就将下一个函数推到微任务队列中,因此现在我们的微任务队列如下所示:微任务队列=[函数秒(x){console.log(x);返回x},函数bfinally(){console.log('its done')}]
对于这个函数来说,又是非常直接的(函数second(x){console.log(x);返回x}),因为这将打印“大家好!”第二次,将另一个句柄注册到微任务队列中,所以现在我们的微任务看起来是这样的:微任务队列=[function bfinally(){console.log('its done')},function third(x){console.log(x);返回x}]
现在,我们从微任务队列(函数bfinally(){console.log('its done')})中获取这个函数,将其放入调用堆栈并运行其中的代码,这只是一个简单的“its done”日志!正如我们所知。最后,它们都不能从先前返回的承诺中获取值,也不能返回供下一个承诺使用的值。因此,这将要做的是运行其中的代码和我们之前编写的代码。最后(…)代码将在我们的根承诺被解析时再次计算为解析承诺!
因为我们用这种方式解决了一个承诺,它将把它的任务注册到微任务队列中,所以现在我们的微任务队列看起来是这样的:微任务队列=[函数三(x){console.log(x);返回x},函数bthen(x){console.log('值为:',x)}]
我们像往常一样从列表中获取第一个任务,运行它,在我们的例子中,它将再次记录“hello everyone”,并注册这个函数“function fourth(x){console.log(x);return x}“现在这是我们的微任务:microtaskqueue=[函数bthen(x){console.log('值为:',x)},函数4th(x){console.log(x);返回x}]
当我们运行这个函数(函数bthen(x){console.log('值为:',x)}),它将打印“值为:true”
在那之后,hello everyone应该多打印三次,因此这应该是我们的最终日志:
hello everyone;
hello everyone;
Its done
hello everyone;
The value is: true
hello everyone;
hello everyone;
hello everyone;
hello everyone;
hello everyone;
但事实并非如此!
我在这个等式中遗漏了什么?
暂无答案!
目前还没有任何答案,快来回答吧!