下面是我摘自著名的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);
} ); 

虽然记录结果的顺序与期望一致,但promise 状态p1显示为待定(在console.log(p1)),这是我无法理解的.我试着通过图片(在最后)描述我到目前为止所理解的东西,这样你就可以纠正我哪里错了.

Result

enter image description here

Stage 1:p1解决了一个已经解决的promise ,p3.我知道p1仍然是悬而未决的,还不会解析出一个值.但我听说resolve(p3)相当于

p3.then(res);  // res is a resolve callback of p1

因此,基于这个假设,由于p3既被解析又具有注册的处理程序(p1的回调res),因此它将被插入到微任务队列(MTQ)中.

Stage 2:p2,它被解析并有一个注册的处理程序(紫色),它将被附加到MTQ.

Stage 3:现在由于堆栈上没有要执行的东西,首先插入到MTQ中的CB(黄色)将进入堆栈以供执行. 我的问题是:当res('B')次执行时,是否会将p1‘S状态标记为已完成?因为res是与p1关联的回调.

由于p1除了被实现之外已经有一个注册的处理程序(当p1.then被调用时),它不会如Stage 4所示附加到MTQ吗?

如果是这样的话,为什么即使在Stage 5的时候,p1仍然显示为等待?

Stage 6:p1是如何一下子得到满足的?

请帮助我理解我在下面的图画描述中哪里错了?

enter image description here

推荐答案

为什么promise 状态显示为pending,而它已经决定了另一个promise ?

这只是terminology美元.该实现不区分"未解决"和"已解决"挂起状态.

p1年执行时,会不会标志着p1年的S状态已经完成?

是.

注册在p1上的回调不会像阶段4中描述的那样附加到MTQ吗?为什么p1甚至在阶段5仍然显示为待定?

你的推理大体上是正确的.是的,会的.事实上,如果您在p1执行回调中编写了p3.then(resolve),这正是会发生的情况,而阶段5 console.log将打印Promise {<fulfilled>: 'B'}.

我听说resolve(p3)等于p3.then(resolve);.所以基于这个假设,…

这一假设并不完全成立.它确实在行为上基本等同,但在微任务计时上不等同.当您将thable(promise )传递给resolve时,它实际上会在新的微任务中调度对.then(resolve, reject)的调用,而不是从resolve()内同步调用它.

    • A:p3被创建,p3"B"来实现
    • B:p1被创建,resolve(p3)访问p3.then,发现它是一个方法,并调度一个回调来调用它
    • C:p2被创建,p2"A"来实现
    • D:p1.then(…)在promise 上注册回调
    • E:p2.then(…)发现p2已经完成,并安排回调
  1. 步骤1b中的任务运行并调用p3.then(resolve, reject)以将其状态采用到p1.它看到p3已经完成,并安排回调
  2. The task from step 1e runs:
    • A:它记录了"In p2"
    • B:记录p1个,仍在等待(但已解析为p3个)
  3. 步骤2中的任务运行并调用resolve("B").这实现了p1并调度了在其上注册的回调.
  4. The task from step 4 runs:
    • A:它记录了"In p1"
    • B:记录p1,在步骤4中已经完成了"B".

您可以阅读规范以了解如此复杂的细节,但您真的不应该依赖它们(它们会随时间变化--事实上,您漏掉的细节是proposed to change).您有两个独立的Promise链,您不应该对p1p2之间的回调顺序做出任何假设.如果这很重要,你会让promise 相互依赖.

Javascript相关问答推荐

从所选的select jQuery中删除多个属性

如何在Node.js中减go 两个日期和时间?

为什么函数不使用以前函数返回的参数?

Math.random超出了最大调用堆栈

Express.js:以块形式发送响应

如何使用CSS和JavaScript创建粘性、凝聚力的形状到形状(容器)变形?

Angular:ng-contract未显示

如何编辑代码FlipDown.js倒计时?

如何在使用fast-xml-parser构建ML时包括属性值?

传递一个大对象以在Express布局中呈现

JQuery. show()工作,但. hide()不工作

Next.js(react)使用moment或不使用日期和时间格式

如何从一个列表中创建一个2列的表?

在执行异步导入之前判断模块是否已导入()

如何修复我的数据表,以使stateSave正常工作?

让chart.js饼图中的一个切片变厚?

AddEventListner,按键事件不工作

使用自动识别发出信号(&Q)

更改agGRID/Reaction中的单元格格式

JavaScript将字符串数字转换为整数