提问人:Sadiq 提问时间:11/16/2023 最后编辑:Sadiq 更新时间:11/16/2023 访问量:88
为什么 promise 状态显示待处理,当它已解析为另一个 promise 时
Why promise state shows pending, when it has resolved to another promise
问:
下面的代码片段我从著名的 YDKJS - Async & Performance 系列中摘录,为了便于理解,做了一些更改。
var p3 = new Promise( function(resolve,reject){
resolve( "B" );
} );
var p1 = new Promise( function(res,rej){
resolve( p3 ); // equivalent to p3.then(res)
} );
var p2 = new Promise( function(resolve,reject){
resolve( "A" );
} );
p1.then( function(v){
console.log("In p1");
console.log(p1);
} );
p2.then( function(v){
console.log("In p2");
console.log(p1);
} );
尽管记录结果的顺序是按照要求进行的,但是承诺 p1 的状态显示挂起 (at ),我无法理解。我试图通过图片(最后)来描述我到目前为止所理解的,所以你可以纠正我错的地方。console.log(p1)
结果
在第 1 阶段:解析为已解析的 promise。我知道仍将保持待处理状态,并且尚未解析为值。但我听说这相当于p1
p3
p1
resolve(p3)
p3.then(res); // res is a resolve callback of p1
因此,基于这个假设,由于既已解析又具有注册的处理程序(callback of ),因此它将入到微任务队列(MTQ)中。p3
res
p1
在第 2 阶段:已解决并具有已注册的处理程序(紫色),它将被附加到 MTQ。p2
在第 3 阶段:现在,由于堆栈上没有要执行的内容,因此首先插入 MTQ 中的 cb(黄色)将进入堆栈进行执行。
以下是我的查询: 执行时,它会将 的状态标记为已完成吗?由于 res 是与 关联的回调。res('B')
p1
p1
由于除了已实现之外已经有一个注册的处理程序(调用时),它不会像第 4 阶段所示附加到 MTQ 中吗?p1
p1.then
如果是这样,那么为什么即使在第 5 阶段仍然显示为待处理?p1
在第 6 阶段:如何突然实现?p1
请帮助我了解我在下面的图片描述中哪里错了?
答:
为什么 promise 状态显示待处理,当它已解析为另一个 promise 时?
这只是术语。该实现不区分“未解决”和“已解决”挂起状态。
执行时,它会将 的状态标记为 Fulfilled 吗?
res('B')
p1
是的。
注册的回调不会像第 4 阶段所示附加到 MTQ 中吗?为什么即使在第 5 阶段仍然显示为待处理?
p1
p1
你的推理大多是正确的。是的,它会的。事实上,如果你在执行回调中写了,这正是会发生的事情,阶段 5 会打印 Promise {<fulfilled>: 'B'}。p3.then(resolve)
p1
console.log
我听说这相当于.所以基于这个假设......
resolve(p3)
p3.then(resolve);
这种假设并不完全有效。它确实在行为上基本等效,但在微任务计时上并不等效。当您将 thenable(承诺)传递给 时,它实际上会在新的微任务中安排对 的调用,而不是从内部同步调用它。resolve
.then(resolve, reject)
resolve()
-
- 答:被创建,被履行
p3
p3
"B"
- b:创建、访问、发现它是一个方法,并调度一个回调来调用它
p1
resolve(p3)
p3.then
- c:被创建,实现
p2
p2
"A"
- d:注册 promise 的回调
p1.then(…)
- e:看到已经实现并安排回调
p2.then(…)
p2
- 答:被创建,被履行
- 步骤 1b 中的任务运行并调用以将其状态采用为 。它看到已经完成并安排回调
p3.then(resolve, reject)
p1
p3
- 步骤 1e 中的任务运行:
- 答:它记录
"In p2"
- b:它记录 ,它仍然处于挂起状态(但已解析为
p1
p3
)
- 答:它记录
- 步骤 2 中的任务运行并调用 。这将实现并计划在其上注册的回调。
resolve("B")
p1
- 步骤 4 中的任务运行:
- 答:它记录
"In p1"
- b:它记录了在步骤 4 中已实现的日志。
p1
"B"
- 答:它记录
你可以阅读规范,了解这些错综复杂的细节,但实际上你不应该依赖它们(而且它们会不时变化——事实上,你错过的细节是建议改变的)。您有两个独立的 promise 链,您不应该对 和 之间的回调顺序做出任何假设。如果它很重要,你会让承诺相互依赖。p1
p2
评论
resolve(p3)
() => resolve("B")
() => p3.then(resolve, reject)
then
() => resolve("B")
评论
resolve(p3)
resolve(Promise.resolve('B')
p3.then
p3
p3.then