最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is it possible to reject each Promise in Promise.allSettled if it takes more than 5 seconds to resolve? - Stack Ove

programmeradmin0浏览0评论

I have a Promise.allSettled which i use to resolve data in the database. I have an array of Promises which I run through the Promise.allSettled, then I only use the resolved ones. Is it possible to set a timeout inside the Promise.allSettled, so that if a promise has still not resolved the data after 5 seconds, it should return as rejected?

My code looks like this:

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

I have a Promise.allSettled which i use to resolve data in the database. I have an array of Promises which I run through the Promise.allSettled, then I only use the resolved ones. Is it possible to set a timeout inside the Promise.allSettled, so that if a promise has still not resolved the data after 5 seconds, it should return as rejected?

My code looks like this:

await Promise.allSettled(promises)
.then(result => result.forEach(d => {
  if (d.status === 'fulfilled') {
    data.push(d.value)
  }
}));
Share Improve this question edited Nov 9, 2021 at 17:00 BML91 3,2004 gold badges37 silver badges56 bronze badges asked Dec 3, 2020 at 10:09 TheStrangerTheStranger 1,5893 gold badges25 silver badges47 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

You could use Promise.race on the original promise and a timeout promise that rejects, e.g.:

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

...where rejectAfterDelay is something like:

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

Side note: You could use filter to filter out the rejected promises:

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

...although I think I'd refactor the "allSettled within timeout" part into a utility function, e.g.:

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");
};

then

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

With a custom Promise class it's easy Demo:

import CPromise from "c-promise2";

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

Such promises can handle cancellation:

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}`);
  });

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论