如果用另一个 promise 解决一个 promise 会发生什么?

What should happen if you resolve a promise with another promise?

ECMAScript 6.0 规范对 Promise 解析另一个 Promise 有何规定?它是否应该通过将 then 附加到可以解决此问题的 Promise 来采用另一个 Promise 的状态?

我在 Chrome 中尝试了这个片段,这是我得到的结果,它似乎只是用 Promise2 解决了 Promise1 这样可以吗?

> Promise1 = new Promise(function(resolve){ResolveYouLater1 = resolve})
> Promise2 = new Promise(function(resolve){ResolveYouLater2 = resolve})
> ResolveYouLater1(Promise2)
  undefined
> Promise1
  Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: Promise}

我认为它应该附加一个 then 到 Promise2,它应该 ResolveYouLater1(value)Promise2 是固定的。

What does the ECMAScript 6.0 specification say about a Promise resolving another Promise?

你可以在这里自己阅读:http://www.ecma-international.org/ecma-262/6.0/#sec-promise-resolve-functions
当参数是 thenable 时,PromiseResolveThenableJob 将被排队。

Should it adopt the state of the other Promise by attaching a then to that Promise which would resolve this one?

是的。 .then() 方法将使用解析器和拒绝器函数调用。

I tried this snippet in Chrome and here is what I get and it seems to just resolve the Promise1 with Promise2 is that fine?

是的。目前只有


我不得不承认,我当前的 Chrome 版本(48.0.2564.82,V8 4.8.271.17)并不完全符合这个算法(这本身可能不是一件坏事,并且 ,但可能出乎意料)。
它是惰性的,只有在实际回调对结果感兴趣时才会安排作业。它不会将解析器传递给 then 方法,而是传递给想要知道结果的实际回调。

> var resolve1, resolve2;
> var promise1 = new Promise(function(r){ resolve1 = r; });
> var promise2 = new Promise(function(r){ resolve2 = r; });
> promise2.then = function(...args) { console.log(...args);
>                                     return Promise.prototype.then.call(this, ...args); };
> resolve1(promise2);
  undefined
// you'd expected a call to the then method here
> promise1
  Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: Promise}
> promise2
  Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
> resolve2(42)
  undefined
// or at least here
> promise1
  Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: Promise}
> promise2
  Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 42}
> promise1.then(x => console.log(x))
  x => console.log(x), PromiseIdRejectHandler() { [native code] }
  // but it only is here
  42
  Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
> promise2.then(x => console.log(x))
  x => console.log(x)
  42
  Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
> promise1.then(x => console.log(x))
  x => console.log(x), PromiseIdRejectHandler() { [native code] }
// hell they're even calling it multiple times!
42
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

> var resolve1, resolve2;
> var promise1 = new Promise(function(r){ resolve1 = r; });
> var thenable = {then:function(r) { console.log(...arguments); resolve2 = r; }};
> resolve1(thenable);
  undefined
// you'd expected a call to the then method here
> promise1
  Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: Object}
> thenable
  Object {}
> resolve2(42)
  Uncaught TypeError: resolve2 is not a function(…)
// uh. yeah.
> promise1.then(x => console.log(x))
  () { [native code] }, () { [native code] }
// ah there was the call, even with a resolver
  Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
> resolve2(42)
  42
  undefined
> promise1.then(x => console.log(x))
  () { [native code] }, () { [native code] }
// but now they fucked up.
// Instead of another call on the thenable, you'd expected the result to be logged
  Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
> resolve2(42)
  42
// OMG.
  undefined