好吧,这会非常冗长。与其他人相反,我会声称,执行顺序console.log
调用在这里是完全确定性的。对于异步代码来说,情况并不总是如此,但是当没有发生任何“真正的”异步代码时,情况仍然经常如此。
为清楚起见,对代码进行了编号:
01 Promise.resolve().then(function() {
02 console.log('promise1');
03
04 Promise.resolve().then(() => {
05 console.log('promise2')
06
07 Promise.resolve().then(() => {
08 console.log('promise3')
09
10 Promise.resolve().then(() => {
11 console.log('promise4')
12 })
13 })
14 })
15 }).then(function() {
16 console.log('promise5');
17
18 Promise.resolve().then(() => {
19 console.log('promise6')
20 })
21 }).then(() => {
22 console.log('promise7')
23 })
提醒:Javascript是单线程的,同一时间只能运行一个。
接下来,每一步都是代码执行,直到上下文被释放,加上由于函数返回而导致的承诺解析。一些调用被省略(例如Promise.resolve()
),因为发生了什么是显而易见的。
在每个步骤的末尾,我将列出当前队列,并且已经执行comment.log
来电。由于每个函数都以console.log
调用,具有唯一的编号,我也将使用它们作为函数的名称。
注意:当一个函数结束时,它又会解决一个承诺,其中有空[[PromiseFulfillReactions]]
,我就不提了,因为这不重要。
程序开始运行...
-
01 Promise.resolve().then(function() {
被调用并入队1
-
15 }).then(function() {
因未解决的承诺而被调用(来自then
在第 1 行)中,等待它解决
-
21 }).then(() => {
因未解决的承诺而被调用(来自then
第 15 行),等待它解决
排队任务:[1]
已经执行的日志:[]
-
02 console.log('promise1');
执行
-
04 Promise.resolve().then(() => {
被调用并入队2
- 返回
undefined
,一个非对象(当然不是then-able,不是一个promise),导致解析从返回的promisethen
在第 1 行中,这又导致其[[PromiseFulfillReactions]]
待执行。唯一添加的反应来自15 }).then(function() {
(往上看)。这排队5
.
排队任务:[2, 5]
已经执行的日志:[1]
-
05 console.log('promise2')
执行
-
07 Promise.resolve().then(() => {
被调用并入队3
排队任务:[5, 3]
已经执行的日志:[1, 2]
-
16 console.log('promise5');
执行
-
18 Promise.resolve().then(() => {
被调用并入队6
- 返回,与上面类似,解决了从返回的承诺
15 }).then(function() {
, 所以就是[[PromiseFulfillReactions]]
执行。这排队7
排队任务:[3, 6, 7]
已经执行的日志:[1, 2, 5]
-
08 console.log('promise3')
执行
-
10 Promise.resolve().then(() => {
被调用并入队4
排队任务:[6, 7, 4]
已经执行的日志:[1, 2, 5, 3]
为了完整起见,我将添加最后的步骤,但从这里开始就非常简单了。
-
19 console.log('promise6')
被执行
排队任务:[7, 4]
已经执行的日志:[1, 2, 5, 3, 6]
-
22 console.log('promise7')
被执行
排队任务:[4]
已经执行的日志:[1, 2, 5, 3, 6, 7]
-
11 console.log('promise4')
被执行
排队任务:[]
empty!
已经执行的日志:[1, 2, 5, 3, 6, 7, 4]
程序终止。