如何处理promise.all拒绝三个承诺中的一个承诺?

时间:2020-11-05 19:12:51

标签: javascript node.js promise promise.all

我有一个特殊的情况,在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得到答复。

请提出如何处理这种情况?

4 个答案:

答案 0 :(得分:1)

使用Promise.allSettled()

它返回ar对象数组,在所有给定的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


所有主流浏览器都支持。因此,您无需使用任何外部库甚至是polyfill。

答案 1 :(得分:0)

您正在寻找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

答案 2 :(得分:0)

您应该考虑使用Observable,因为它比较容易处理,但是您仍然可以使用promises。

您将要使用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,
      })])
    ]);

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

答案 3 :(得分:0)

bluebird是一个出色的Promises库。 它具有timeout函数,在这里将非常有用。

const Promise = require('bluebird');

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