【问题标题】:How to have single finally handler for multiple promises in AngularJS?如何在 AngularJS 中为多个 Promise 提供单个 finally 处理程序?
【发布时间】:2017-01-04 05:24:15
【问题描述】:

我有两个相互独立的承诺,我想在两个承诺都完成(拒绝或解决)之后执行最后一步。

$q.all() 不能使用,因为我希望 finally 始终执行(两个 Promise 只执行一次),即使任何 Promise 拒绝

一种解决方案可能是有一个计数器并有一个 finallyHandler 函数来在两个 Promise 都解决/拒绝时执行它。

  var count = 0;
  function finallyHandler() {
    if ( ++count === 2 ) {
      doStuff();
      count = 0;
      }
  }

firstPromise.finally(finallyHandler);
secondPromise.finally(finallyHandler);

这可以工作,但看起来不对。

有没有更好的方法来做到这一点?

【问题讨论】:

  • 第三个 Promise 在解决或拒绝时都解决了怎么办?这将使代码更易于阅读和维护。
  • @briosheje 有正确的想法。构建 promise 数组,以便每个 promise 都有自己的传递错误行为。 promises.push( doStuff().catch(e => e) ),然后将 Promise.all 应用到 promises

标签: javascript angularjs angular-promise


【解决方案1】:

Promise.all(iterable) 会做你想要的。但是,请查看浏览器的兼容性,因为 Internet Exploer 不支持此方法。来自文档:

Promise.all(iterable) 方法返回一个承诺,当 可迭代参数中的所有承诺都已解决或拒绝 第一个通过的 promise 被拒绝的原因。

使用您的代码示例(带有失败行为),它看起来像这样:

Promise.all([firstPromise, secondPromise]).then(values => { 
    finallyHandler();
}, reason => {
    finallyHandler();
});

即使失败块与成功块相同,但成功块仅在所有承诺成功完成后运行,失败块运行一次(并且仅一次)遇到第一个失败。

参考:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

【讨论】:

    【解决方案2】:

    通常$q.all 在第一个被拒绝的承诺上解决被拒绝并且不等待其他承诺。要等待所有承诺解决已履行或拒绝,请制作每个承诺的弹性版本,然后在这些版本上使用 $q.all

    var resiliantFirstPromise = firstPromise.catch(e => "CONVERTED");
    var resiliantSecondPromise = secondPromise.catch(e => "CONVERTED");
    
    $q.all([resiliantFirstPromise, resiliantSecondPromise])
      .then(() => {
        console.log("Both promises have resolved");
    });
    

    通过向.catch 方法返回一个值,每个被拒绝的promise 都会返回一个已转换为已履行的promise 的派生promise。 由于没有一个派生promise 被拒绝,$q.all将等待两个 Promise 都被解决(履行或拒绝)。

    【讨论】:

    • 这看起来很整洁,效果很好!我对 both promise to be resolved 部分感到困惑,因为 resolve 通常意味着 fulfilled。因此,将其更改为“..待解决(履行或拒绝)”是一个更好的主意
    • 虽然我同意有些人错误地使用 resolved 来表示 resolved 完成,但 Promises/A+ Spec 使用术语“解决方案”来表示从“未决”状态为“已完成”或“已拒绝”。我宁愿坚持这个术语也不愿引入一个新词。见Promises/A+ The Promise Resolution Procedure
    【解决方案3】:
    firstPromise().catch().secondPromise().catch().then(//what you want)
    

    上面的promise链可以做到这一点。最终的then 在所有情况下都会被调用。 catch 将传播承诺拒绝。

    【讨论】:

    • 看起来我没有正确地问这个问题。 finally 只有在两个承诺都完成(拒绝或解决)时才应该被调用。我想等待所有的承诺都完成。所以这将无法正常工作。
    【解决方案4】:

    你会用吗?

    Promise.All([array of promises],handler)
    

    Promise.All Docs

    或者像 BlueBirdAsyncjs 这样的库?

    【讨论】:

      猜你喜欢
      • 2021-06-02
      • 1970-01-01
      • 2014-05-24
      • 2015-08-24
      • 2012-10-13
      • 2018-02-23
      • 1970-01-01
      • 2017-08-05
      • 1970-01-01
      相关资源
      最近更新 更多