【问题标题】:How to handle promise.all rejecting one promise out of three promises? [duplicate]如何处理promise.all拒绝三个promise中的一个promise? [复制]
【发布时间】:2020-11-05 19:12:51
【问题描述】:

我有一个独特的情况,两个 Promise 在 Promise.all 中一起运行。 但其中一个承诺需要很长时间,因此我没有得到任何结果。 除了一个,其他承诺正在得到解决。 我想用错误消息拒绝需要很长时间(例如:如果超过 60 秒)的承诺,以便我可以从 Promise.all 获得响应。

例如::

const [client1Prices, client2Prices] = await Promise.all([
      this.client1.getSimulationPrices({
        hourPay: journey.hourPay,
        jobType: journey.jobType,
        salary: journey.salary,
        weeklyHours: journey.weeklyHours,
      }),
      this.client2.getSimulationPrices({   // takes more than 60 sec and i want to reject this promise
        hourPay: journey.hourPay,
        jobType: journey.jobType,
        salary: journey.salary,
        weeklyHours: journey.weeklyHours,
      })
    ]);

this.client2.getSimulationPrices 需要花费大量时间来解决,因此 Promise.all 没有给我任何结果。我想在 60 秒内拒绝这个,这样我就可以得到 Promise.all 的响应。

请建议如何处理这种情况?

【问题讨论】:

  • 如果第二个 promise 被拒绝,您是否期望能够访问第一个 promise 的结果?
  • 是的,我期待第一个承诺的结果和第二个承诺的一些错误消息。
  • Promise.all() 如果一个人拒绝,他们都会拒绝。 (本质上)
  • 这就是为什么我想用某种形式的错误消息来处理需要很长时间的承诺,如果它需要更多时间,以便我可以继续做进一步的任务。
  • 我的方法失败了。什么是最好的解决方案?

标签: javascript node.js promise promise.all


【解决方案1】:

使用Promise.allSettled()

它返回 ar 对象数组 Promise,在所有给定的 Promise 都已实现或拒绝后解析。

数组中的每个对象都描述了每个承诺的结果。

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'Prmoise 2'));
const promise3 = new Promise((resolve, reject) => setTimeout(resolve, 200, 'Promise 3'));

const promise4 = new Promise((resolve, reject) => setTimeout(reject, 200, 'Promise 4'));

const promises = [promise1, promise2, promise3, promise4];

Promise.allSettled(promises).
then((results) => results.forEach((result) => console.log(result.status)));

// expected output:

// "fulfilled"
// "rejected"
// "fulfilled"
// "rejected"

更多信息

Promise.allSettled() - MDN


所有主流浏览器都支持它。所以你不需要使用任何外部库甚至 polyfills。

【讨论】:

    【解决方案2】:

    您正在寻找Promise.allSettled()。与Promise.all() 不同,如果任何承诺失败,它不会抛出错误。相反,结果是一个对象:

    {
        status: 'fulfilled',
        value: return_value
    }
    

    如果没有错误或:

    {
        status: 'rejected',
        reason: error_message
    }
    

    如果有错误。

    MDN 表示节点 12.9.0 及更高版本支持此功能。如果您在没有它的环境中需要它,npm 上有一个纯 js 实现:https://www.npmjs.com/package/promise.allsettled

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

    【讨论】:

    • 这并没有解决超时问题。如果 promise 花费的时间超过 60 秒(成功或失败),Promise.allSettled() 仍然会等待太长时间才能解决。
    【解决方案3】:

    您应该考虑使用 observables,因为这更容易处理,但是,您仍然可以使用 Promise 来做到这一点。

    你会想要使用Promise.race()

    Promise.race() 方法返回一个承诺,一旦可迭代中的一个承诺履行或拒绝,该承诺就会履行或拒绝,并带有来自该承诺的价值或原因。

    const timeoutPromise = new Promise((resolve, reject) => setTimeout(() => reject('TIMEOUT'), 60000));
    });
    const [client1Prices, client2Prices] = await Promise.all([
          this.client1.getSimulationPrices({
            hourPay: journey.hourPay,
            jobType: journey.jobType,
            salary: journey.salary,
            weeklyHours: journey.weeklyHours,
          }),
          Promise.race([timeoutPromise, this.client2.getSimulationPrices({
            hourPay: journey.hourPay,
            jobType: journey.jobType,
            salary: journey.salary,
            weeklyHours: journey.weeklyHours,
          })])
        ]);
    

    保证client2Prices 在 60 秒或更短时间内返回。您可以检查该值以确定它是否超时或是否成功。如果你想吞下超时错误(没有Promise.all()失败,你可以让超时resolve(而不是reject),或者切换到使用Promise.allSettled()

    【讨论】:

      【解决方案4】:

      一个优秀的 Promises 库是 bluebird。 它有一个timeout 函数,在这里证明是有用的。

      const Promise = require('bluebird');
      
      const [client1Prices, client2Prices] = await Promise.allSettled([
            this.client1.getSimulationPrices(...).timeout(60000),
            this.client2.getSimulationPrices(...).timeout(60000)
          ]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-10
        • 2017-04-24
        • 1970-01-01
        • 2020-08-08
        • 2020-08-06
        • 1970-01-01
        • 2022-01-18
        • 2015-04-26
        相关资源
        最近更新 更多