javascript - Promise/A+ 规范的哪一部分要求 Promise 必须从返回的 Promise 吸收状态?

标签 javascript promise

我正在编写一个 Promise 库,我对它的部分测试套件感到困惑 ( https://github.com/promises-aplus/promises-tests )。

有许多类似的测试(为了便于阅读而进行了简化):

 var promise = new Promise();

 var done = false;
 var was_resolved = false;
 var was_rejected = false;

 promise.resolve('dummy').then(function() {
   done = true;
   return new Promise();
 });

 promise.then(
   function() { was_resolved = true; },
   function() { was_rejected = true; }
 );

 asyncAssert(function() {
   assert.true(done)
   assert.false(was_resolved);
   assert.false(was_rejected);
 });

现在,我明白了这个测试的原理;如果 Promise 的解析函数返回 Promise,则吸收该 Promise 的状态(在本例中为待处理)。

因此,在 Promise 本身得到解决之前,第二个 then 函数调用的回调不会得到解决。

但是,仔细查看此处的规范 ( http://promises-aplus.github.io/promises-spec/ ),我看不到任何强制执行此行为的内容。

相关点似乎是:

2.2.7 then must return a promise [[3.3](#notes)].
promise2 = promise1.then(onFulfilled, onRejected);

2.2.7.1If either onFulfilled or onRejected returns a value x, run the 
Promise Resolution Procedure [[Resolve]](promise2, x).

和:

To run [[Resolve]](promise, x), perform the following steps:
2.3.2 If x is a promise, adopt its state [[3.4](#notes)]: 

但是,如果我们仔细观察代码,我们会发现 Promise 解析过程应该是:

var promise = new Promise(); <--- Promise (1)

var promise2 = promise.resolve('dummy').then(function() { <--- Promise (2)
   return new Promise(); <--- Promise (3)
 }); 

var promise4 = promise.then( <--- Promise (4)
   function() { was_resolved = true; },
   function() { was_rejected = true; }
 );

请注意,当前的“ promise 堆栈”如下:

- Promise 1 
-- resolve, undefined -> promise 2
-- resolve, reject -> promise 4

异步 ​​.resolve('dummy') 调用的解决方案:

[[Resolve]](1, dummy):
- 2.3.4 forfill promise (1) with 'dummy'
-- Next item on the promise stack for (1)
--- execute resolve
--- return is promise (3)
--- 2.2.7.1 run [[Resolve]](2, promise 3)
-- Next item on the promise stack for (1)
--- execute resolve 
--- return is undefined
--- 2.2.7.3 forfill promise (4) with 'dummy'

请注意,Promise 2 处于待处理状态,但 Promise 1 却没有处于待处理状态,因为 Promise 本身从未调用过 [Resolve]。如果 then() 返回一个 Promise,即 Promise 2,我们会对该 Promise 运行解析(请参阅规范中的 2.2.7)。

现在根据规范:

Notes 3.3 Implementations may allow promise2 === promise1, provided the implementation
meets all requirements. Each implementation should document whether it can produce 
promise2 === promise1 and under what conditions.

...但这似乎不是真的。

看起来测试套件要求 2.2.7 中返回的 promise 成为原始 promise ,这样当 2.2.7.1 运行时,它会在本身。

如果我们看看这里的“基本”实现: https://github.com/then/promise/blob/master/core.js

我们看到handle()函数确实做了一些奇怪的事情,它这样做是为了履行 promise p:

then() {
  ...
  return new Promise();
}

forfill(p) {
  action = pick appropriate action (p.reject or p.resolve)
  result = action()
  p.resolve(result)
}

规范不是这么说的。规范明确指出:

then must return a promise
promise2 = promise1.then(onFulfilled, onRejected);

If either onFulfilled or onRejected returns a value x,
run the Promise Resolution Procedure [[Resolve]](promise2, x).

但这似乎正在做的是:

then must return a promise
promise2 = promise1.then(onFulfilled, onRejected);

If either onFulfilled or onRejected returns a value x,
run the Promise Resolution Procedure [[Resolve]](***promise1***, x).

请注意,在“引用”实现中,被调用的 onFulfilled 和 onRejected 项是与 Promise1 关联的项,而不是与 Promise2 关联的项。

也许我完全误解了规范的措辞?

我在这里缺少什么?

如果我正在编写 Promise 实现,我是否应该忽略规范并从引用示例中复制实现细节?

最佳答案

What am I missing here?

一点后缀:-)

a number of tests along these lines (simplified for readability)

你似乎过于简单化了https://github.com/promises-aplus/promises-tests/blob/master/lib/tests/2.3.2.js 。它的代码更像

var promise1 = new Promise().resolve('dummy');

var promise2 = promise1.then(function() {
  return promise3 = new Promise();
}); 

var promise4 = promise2.then(
//                    ^ look here!
  function() { was_resolved = true; },
  function() { was_rejected = true; }
);

现在“ promise 堆栈”如下所示:

- promise 1 
-- resolve, undefined -> promise 2
- promise 2
-- resolve, reject -> promise 4

promise4 处于待处理状态,因为它依赖于promise2,而promise2 处于待处理状态,因为它采用了从 Unresolved promise3。

If I'm writing a promises implementation should I just ignore the spec

没有。绝不。您绝对应该尝试理解它及其背后的推理(如果不清楚,请提出问题)。如果您不同意规范的某些部分,您仍然可以编写不合格的实现,但您应该首先尝试:-)

关于javascript - Promise/A+ 规范的哪一部分要求 Promise 必须从返回的 Promise 吸收状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21902166/

相关文章:

javascript - React 不会从 firebase 渲染数组值,并且数组的长度为 0,尽管控制台上有该值

javascript - 在类中实现链式 es6 Promise

javascript - NodeJS promise 解析

javascript - 使用构造函数创建 "universe"的简单模拟

javascript - 使用 .map() 为 JS 对象添加增量值

javascript - 如果 Knockout 在计算中包装了一个有界函数表达式,为什么它并不总是创建一个依赖项?

javascript - Promise.all 不等待函数完成

javascript - Highcharts 根据动态货币对绘制时间

javascript - 如何使用 javascript/jquery 使 <a> 标签元素触发多个功能

javascript - 为什么不能将 Promise.resolve 作为函数调用?