当我了解 microtask 和 Promise 时,我遇到了一个我不明白的行为
when I learned about microtask and Promise , I came across a behavior I don't understand
我没有return then() 回调里的东西,我认为输出应该是 1 5 7 2 6 3 4,但结果是 1 2 5 3 6 7 4,谁能告诉我为什么
Promise.resolve().then(function() {
console.log('promise1');
Promise.resolve().then(() => {
console.log('promise2')
Promise.resolve().then(() => {
console.log('promise3')
Promise.resolve().then(() => {
console.log('promise4')
})
})
})
}).then(function() {
console.log('promise5');
Promise.resolve().then(() => {
console.log('promise6')
})
}).then(() => {
console.log('promise7')
})
好吧,这会很冗长。与其他人相反,我会声称,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 resolving 因为函数返回。省略了一些调用(例如 Promise.resolve()
),因为它很明显,会发生什么。
在每个步骤结束时,我将列出当前队列和已执行的 comment.log
个调用。由于每个函数都以 console.log
调用开头,具有唯一编号,因此我也将使用它们作为函数的名称。
注意:当一个函数结束时,它又解析了一个空的 promise [[PromiseFulfillReactions]]
,我不会提到它,因为它不重要。
程序开始运行宁...
01 Promise.resolve().then(function() {
被调用并入队 1
15 }).then(function() {
在未解决的承诺上被调用(来自第 1 行的 then
),等待它解决
21 }).then(() => {
在未解决的承诺上被调用(来自第 15 行的 then
),等待它解决
排队的任务:[1]
已经执行的日志:[]
02 console.log('promise1');
执行
04 Promise.resolve().then(() => {
被调用并入队 2
- 返回
undefined
,一个非对象(当然不是 then-able,不是一个 promise),导致解析从第 1 行的 then
返回的 promise,这反过来导致它的 [[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')
被执行
排队的任务:[]
空!
已经执行的日志:[1, 2, 5, 3, 6, 7, 4]
程序终止。
我没有return then() 回调里的东西,我认为输出应该是 1 5 7 2 6 3 4,但结果是 1 2 5 3 6 7 4,谁能告诉我为什么
Promise.resolve().then(function() {
console.log('promise1');
Promise.resolve().then(() => {
console.log('promise2')
Promise.resolve().then(() => {
console.log('promise3')
Promise.resolve().then(() => {
console.log('promise4')
})
})
})
}).then(function() {
console.log('promise5');
Promise.resolve().then(() => {
console.log('promise6')
})
}).then(() => {
console.log('promise7')
})
好吧,这会很冗长。与其他人相反,我会声称,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 resolving 因为函数返回。省略了一些调用(例如 Promise.resolve()
),因为它很明显,会发生什么。
在每个步骤结束时,我将列出当前队列和已执行的 comment.log
个调用。由于每个函数都以 console.log
调用开头,具有唯一编号,因此我也将使用它们作为函数的名称。
注意:当一个函数结束时,它又解析了一个空的 promise [[PromiseFulfillReactions]]
,我不会提到它,因为它不重要。
程序开始运行宁...
01 Promise.resolve().then(function() {
被调用并入队1
15 }).then(function() {
在未解决的承诺上被调用(来自第 1 行的then
),等待它解决21 }).then(() => {
在未解决的承诺上被调用(来自第 15 行的then
),等待它解决
排队的任务:[1]
已经执行的日志:[]
02 console.log('promise1');
执行04 Promise.resolve().then(() => {
被调用并入队2
- 返回
undefined
,一个非对象(当然不是 then-able,不是一个 promise),导致解析从第 1 行的then
返回的 promise,这反过来导致它的[[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')
被执行
排队的任务:[]
空!
已经执行的日志:[1, 2, 5, 3, 6, 7, 4]
程序终止。