已解决的承诺等待内部承诺得到解决

时间:2017-10-21 20:47:59

标签: javascript promise

我想承诺一个承诺,就像这样:

let first = new Promise(resolveFirst => {
    setTimeout(() => {
        resolveFirst("resolved!");
    }, 2000)
});

let second = new Promise(resolveSecond => {
    setTimeout(() => {
        resolveSecond(first);
    }, 10)
});

second.then(secondValue => {
    console.log("second value: ", secondValue);
    secondValue.then(firstValue => {
        console.log("first value: ", firstValue);
    });
});

这样console.log("second value: ", secondValue);10毫秒后打印,然后console.log("first value: ", firstValue)将被打印2000

虽然我得到了:

  

第二个值:已解决!

错误:

  

未捕获(承诺)TypeError:secondValue.then不是函数

2010毫秒之后一起。

似乎当第二个承诺得到解决,并且第一个承诺被返回时,它会自动等待第一个承诺解决。

为什么?我怎么在他们之间打破?

修改

以下是使用Array.reduce()在Facebook上发布的解决方案:

const runPromisesInSeries = 
    ps => ps.reduce((p, next) => 
        p.then(next), Promise.resolve());

const delay = d => new Promise(r => setTimeout(r, d));
runPromisesInSeries([() => delay(1000), () => delay(2000)]);
//executes each promise sequentially, taking a total of 3 seconds to complete

https://www.facebook.com/addyosmaniofficial/photos/a.10151435123819601.1073741825.129712729600/10155386805609601/?type=3&theater

3 个答案:

答案 0 :(得分:3)

按照设计,在第二个承诺得到解决(履行或拒绝)后,以第二个承诺解决的承诺将承担第二个承诺的价值和状态,等待必要时将其结算。

除非promise库存在严重缺陷,否则不可能使用promise或者thenable对象(具有then method`)值的任何对象来履行承诺(旧版本的JQuery将使用它们自己的promise对象)来自不同图书馆的承诺对象。)

承诺拒绝没有相同的检查,并且很乐意将承诺对象传递到链中而不等待它被解决。所以你可以用第一个承诺拒绝第二个承诺并在catch子句中选择它。

虽然技术上可行但我强烈建议不要这样做,除非证明可以这样做 - 这对于试图理解代码的第三方来说是一个维护问题。

虽然您可以将承诺作为对象属性传递到承诺链的成功渠道,但对承诺组合的重新分析可以提供更好或更标准的解决方案。例如。在继续执行共同任务之前,Promise.all等待两个或更多独立承诺得以履行。

答案 1 :(得分:1)

这只是他们魅力的一部分:如果你的承诺A解析为一个可靠的B,那么只有在B结算后A才会解决,而A会获得B的解析值。这是Promises/A+ES6的一部分,是“承诺解决程序”的一部分。

如果(比方说)一个动作在完成之前需要一个动作(比如登录),或者需要加载另一个结果页面,或者有自己的重试逻辑,你可以看到一些优点。

虽然它不是非常惯用,但是如果你想立即返回一个未解决的承诺而不等待它,你可以通过{object}[array]传递它,但可能没有多少原因是:除了等待完成之外,你会对退回的承诺做些什么?

答案 2 :(得分:0)

您只能将then链接到承诺。 secondValue不是承诺,它只是您调用second承诺时返回的值。或该承诺的resolved值。

如果您希望这样做,请尝试以下方法:

let first = new Promise(resolveFirst => {
  setTimeout(() => {
    resolveFirst("resolved!");
  }, 2000)
});

let second = new Promise(resolveSecond => {
  setTimeout(() => {
    resolveSecond(first);
  }, 10)
});

second.then(secondValue => {
    console.log("second value: ", secondValue);
    /** first is a Promise. return a promise, and the next "then"
     * will pass the result of that Promise.
     */
    return first
  })
  .then(firstValue => {
    console.log(firstValue)
  })

编辑1

进一步解释为什么second承诺解决了string承诺的最终价值(first),而不是承诺本身,can be found on mdn:

<强> Promise.resolve()

  

如果值是promise,则该对象成为对Promise.resolve的调用的结果;否则返回的承诺将用值来实现。