使用Promise.allSettled前出现未捕获Promise错误问题求助
问题原因及解决方案
问题根源
你遇到的未捕获Promise错误,核心原因是:Promise实例在创建时就会立即执行,而非等到Promise.allSettled调用时才启动。
在你的代码中,当循环到val=4时,调用fakeTimerError()生成了一个Promise,这个Promise会在300ms后触发reject。但此时循环还在等待fakeTimer('test1')的2000ms执行完成,这个提前触发的reject没有被任何catch语句捕获,因此直接抛出未捕获的Promise错误,根本没等到后续Promise.allSettled执行。
解决方案
方案1:延迟Promise创建(推荐)
不要提前生成Promise实例,而是将生成Promise的逻辑(函数或参数)存入数组,等循环结束后再统一创建并执行所有Promise。这样所有Promise会在Promise.allSettled调用时才开始执行,不会提前触发reject:
(async function () { const fakeTimer = (val) => new Promise(res => setTimeout(() => res(val), 2000)) const fakeTimerError = () => new Promise((res, rej) => setTimeout(() => rej('Hello'), 300)) var arr = [1, 2, 4, 6,7, 3] var promiseFactories = [] try { for (let val of arr) { await fakeTimer('test1') if (val === 4) { promiseFactories.push(fakeTimerError) } else { promiseFactories.push(() => fakeTimer(val)) } } // 统一生成Promise并执行 const res = await Promise.allSettled(promiseFactories.map(fn => fn())) console.log(res) } catch (error) { console.log('error', error) } })()
方案2:给单个Promise添加catch处理
如果必须提前创建Promise实例,可以给每个可能reject的Promise单独添加catch,提前捕获reject以避免未捕获错误。这样Promise.allSettled仍能正常收集所有结果:
(async function () { const fakeTimer = (val) => new Promise(res => setTimeout(() => res(val), 2000)) const fakeTimerError = () => new Promise((res, rej) => setTimeout(() => rej('Hello'), 300)) var arr = [1, 2, 4, 6,7, 3] var promises = [] try { for (let val of arr) { await fakeTimer('test1') if (val === 4) { // 提前捕获reject,避免未捕获错误 promises.push(fakeTimerError().catch(err => err)) } else { promises.push(fakeTimer(val)) } } const res = await Promise.allSettled(promises) console.log(res) } catch (error) { console.log('error', error) } })()
内容的提问来源于stack exchange,提问作者Adil Liaqat
相关产品推荐
相关产品推荐

