如何通过async函数抛出错误跳出循环,解决未处理Promise拒绝报错
问题根因
你代码触发ERR_UNHANDLED_REJECTION报错的核心原因是:调用async_function()时没有使用await,也没有挂载catch回调。外层的try...catch只能捕获当前上下文内同步抛出的错误、以及被await的Promise的拒绝错误,而你调用的async_function是独立运行的异步任务,它抛出的错误没有被任何处理器捕获,就会触发全局报错。
同时你原来的逻辑里,async_function的执行状态完全没有和循环逻辑做关联,自然也无法触发循环终止。
最优实现方案
不推荐用「抛错误」的方式做正常业务流程的控制,更合理的方式是用Promise.race关联主任务和循环任务的执行状态,示例代码如下:
async function async_function(){ await new Promise(r=>setTimeout(r,3000)); // 正常返回即可标识任务完成,无需抛错 return 'task completed' } async function do_something_meanwhile() { await new Promise(r => setTimeout(r, 500)); console.log(Math.floor(Math.random()*10)); } (async ()=>{ // 先启动主异步任务,拿到它的Promise实例 const mainTask = async_function(); let isMainTaskFinished = false; try { while (!isMainTaskFinished) { // 单次循环同时监听「当前次循环任务」和「主任务完成状态」 await Promise.race([ do_something_meanwhile(), mainTask.then(result => { // 主任务先执行完的话,修改标记终止下一轮循环 isMainTaskFinished = true; console.log('主任务执行完成,结果:', result); }) ]); } } catch (err) { console.log('exited with error:',err) } console.log('moving on'); })();
原写法兼容方案
如果你坚持要用抛错的方式触发终止,只需要给async_function挂载错误回调,把错误传入当前上下文即可:
// 只修改try块内的逻辑即可 try { const mainTask = async_function().catch(err => {throw err}); let isMainTaskFinished = false; while (!isMainTaskFinished) { await Promise.race([ do_something_meanwhile(), mainTask.finally(() => isMainTaskFinished = true) ]) } } catch (err) { console.log('exited with error:',err) }
内容的提问来源于stack exchange,提问作者user15573857
相关产品推荐
相关产品推荐

