当承诺因超时而被拒绝时,避免未捕获的异常?

Avoid uncaught exception when a promise gets rejected due to timeout?

我的 node.js 程序中有一个情况,我有一系列承诺。我准备为数组中的每个承诺最多等待 200 毫秒才能实现,如果到那时还没有实现,我希望它被拒绝。

当我 运行 我在终端中使用 node.js 我的脚本而没有附加调试器时,我为此编写的代码有效。

但是,当我使用 VS 代码调试同一脚本时,它会在 promise 由于超时而被拒绝时立即停止。调试器声称拒绝是未捕获的异常。

我如何更改我的代码,使其完全按照现在的方式执行,但被拒绝的承诺不会导致异常?

我试过到处添加 try{}catch{},但似乎找不到解决方案。

这是我的问题的一个最小可重现示例(调试器抱怨行 reject( "timeout" ) ):

async function delayedPromise(delay) {
  await new Promise((res) => setTimeout(res, delay));
  return "success";
}

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

async function main() {

  // Create array of promises.
  promArr = [];
  promArr.push(delayedPromise(100));
  promArr.push(delayedPromise(200));
  promArr.push(delayedPromise(300));
  promArr.push(delayedPromise(400));
  promArr.push(delayedPromise(500));

  // Wait for all promises to either get fulfilled or get rejected after 200 ms.
  const msMaxTime = 200;
  const result = await Promise.allSettled(
    promArr.map(promise => Promise.race([promise, rejectAfterDelay(msMaxTime)]))
  );

  console.log(result);
}
main()

我们可以将承诺包装在 short-lived 承诺中,而不是使用 short-lived 承诺(rejectAfterDelay)进行承诺:

async function delayedPromise(delay) {
  return new Promise((res) => setTimeout(res, delay, 'success'));
}

// wrap the promise instead of racing it
function rejectAfterDelay(promise, ms) {
  return new Promise((resolve, reject) => {
    setTimeout(reject, ms, 'timeout');
    // forward the reasons to the wrapper
    promise.then(reason => resolve(reason))
           .catch(err => reject(err));
  });
}

async function main() {

  // Create array of promises.
  promArr = [];
  promArr.push(delayedPromise(100));
  promArr.push(delayedPromise(200));
  promArr.push(delayedPromise(300));
  promArr.push(delayedPromise(400));
  promArr.push(delayedPromise(500));

  // Wait for all promises to either get fulfilled or get rejected after 200 ms.
  const msMaxTime = 200;
  const result = await Promise.allSettled(
    promArr.map(promise => {
      //return Promise.race([promise, rejectAfterDelay(msMaxTime)]);
      return rejectAfterDelay(promise, msMaxTime);
    })
  );

  console.log(result.map(r => r.value ? r.value : r.reason));
}
main()

有了这个,调试器在选择 Uncaught Exceptions 选项时不会报错。
此外,根据您的情况,您可以使用 setTimeout(resolve, ms, 'timeout') 代替 setTimeout(reject, ms, 'timeout') 使其优雅地失败。