如果解决时间超过 5 秒,是不是可以拒绝 Promise.allSettled 中的每个 Promise?

Posted

技术标签:

【中文标题】如果解决时间超过 5 秒,是不是可以拒绝 Promise.allSettled 中的每个 Promise?【英文标题】:Is it possible to reject each Promise in Promise.allSettled if it takes more than 5 seconds to resolve?如果解决时间超过 5 秒,是否可以拒绝 Promise.allSettled 中的每个 Promise? 【发布时间】:2021-03-15 08:14:44 【问题描述】:

我有一个 Promise.allSettled 用于解析数据库中的数据。我有一组通过 Promise.allSettled 运行的 Promise,然后我只使用已解决的 Promise。是否可以在 Promise.allSettled 中设置超时,这样如果一个 Promise 在 5 秒后仍未解决数据,它应该返回为被拒绝?

我的代码如下所示:

await Promise.allSettled(promises)
.then(result => result.forEach(d => 
  if (d.status === 'fulfilled') 
    data.push(d.value)
  
));

【问题讨论】:

【参考方案1】:

您可以在原始承诺和拒绝的超时承诺上使用Promise.race,例如:

await Promise.allSettled(
    promises.map(promise => Promise.race([promise, rejectAfterDelay(5000)])) // **
)
.then(result => result.forEach(d => 
  if (d.status === 'fulfilled') 
    data.push(d.value)
  
));

...rejectAfterDelay 类似于:

const rejectAfterDelay = ms => new Promise((_, reject) => 
    setTimeout(reject, ms, new Error("timeout"));
;

旁注:您可以使用filter 过滤掉被拒绝的承诺:

data.push(...
    await Promise.allSettled(
        promises.map(promise => Promise.race([promise, rejectAfterDelay(5000)]))
    ).then(result => result.filter((status) => status === "fulfilled"))
);

...虽然我认为我会将“allSettled 在超时内”部分重构为实用函数,例如:

const fulfilledWithinTimeout = async (promises, timeout) => 
    promises = Array.isArray(promises) ? promises : [...promises];
    const all = await Promise.allSettled(promises.map(promise => Promise.race([promise, rejectAfterDelay(timeout)]));
    return all.filter((status) => status === "fulfilled");
;

然后

data.push(...await fulfilledWithinTimeout(promises, 5000));

【讨论】:

最后一个与旁注相关的问题。我可以过滤结果然后仅获取值列表吗?因此,您的代码过滤列表,因此列表中仅保留“已完成”。现在我还想要一个仅包含已完成值对象的列表。 :) 谢谢你 @Benji - 您通常会在 filter 之后使用 mapresult => result.filter((status) => status === "fulfilled").map((value) => value)【参考方案2】:

使用自定义 Promise 类很容易Demo:

import CPromise from "c-promise2";

CPromise.allSettled([...promises])
  .timeout(1000)
  .catch((err) => 
    console.warn(`Fail: $err`); // Fail: CanceledError: timeout 
  );

这样的承诺可以处理取消:

import CPromise from "c-promise2";

CPromise.allSettled([
  new CPromise((resolve, reject,  onCancel ) => 
    const timer = setTimeout(resolve, 2000);
    onCancel(() => 
      clearTimeout(timer);
      console.log("Wow! timeout cleared");
    );
  )
])
  .timeout(1000)
  .catch((err) => 
    console.warn(`Fail: $err`);
  );

【讨论】:

以上是关于如果解决时间超过 5 秒,是不是可以拒绝 Promise.allSettled 中的每个 Promise?的主要内容,如果未能解决你的问题,请参考以下文章

怎样提高开机速度?怎样提高主板启动速度?如果提升超过5秒,重磅悬赏!!电脑配置见 问题补充 。

缓慢的Http拒绝服务攻击漏洞的验证(slowhttptest的安装)

确定 95% 的请求所用时间不超过 1 秒,如果超过则自动停止测试

Hystrix circuit short-circuited and is OPEN 异常

如果运行超过 x 秒,SQL 查询返回一个值?

怎样提高开机速度?怎样提高主板启动速度?如果提升超过5秒,重磅悬赏!!电脑配置见 问题补充 。