0

我有一个独特的情况,其中两个 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 的响应。

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

4

4 回答 4

1

利用Promise.allSettled()

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

于 2020-11-05T19:35:29.053 回答
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

于 2020-11-05T19:26:05.850 回答
0

您应该考虑使用 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()

于 2020-11-05T19:26:10.590 回答
0

一个优秀的 Promises 库是bluebird。它有一个timeout在这里证明有用的功能。

const Promise = require('bluebird');

const [client1Prices, client2Prices] = await Promise.allSettled([
      this.client1.getSimulationPrices(...).timeout(60000),
      this.client2.getSimulationPrices(...).timeout(60000)
    ]);
于 2020-11-05T19:26:30.950 回答