当承诺因超时而被拒绝时,避免未捕获的异常?
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')
使其优雅地失败。
我的 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')
使其优雅地失败。