自定义Promise.all实现中async函数的错误未被处理问题排查
自定义Promise.all实现中async函数的错误未被处理问题排查
我来帮你拆解下问题出在哪,以及怎么修复:
问题1:顺序执行导致Promise提前reject未被捕获
你的promiseAllAsyncAwait用了for循环逐个await任务,这会让Promise串行执行:必须等asyncTask1跑完(1000ms),才会开始处理asyncTask2。但asyncTask2的reject会在500ms时触发,这时候这个已拒绝的Promise还没被你的await处理,相当于没有任何catch捕获它的错误,所以Node.js会抛出UnhandledPromiseRejection错误,甚至可能提前终止程序,导致后续的console.log(123)根本没机会执行。
问题2:错误处理逻辑有误
就算代码能走到asyncTask2的catch块,你用了return err而不是throw err。对async函数来说,return一个值会让它返回的Promise变成resolved状态(值就是你return的内容),而不是rejected。所以外面的try/catch不会进入catch块,因为await的是一个已resolved的Promise。
修复方案
要实现和原生Promise.all一致的并行执行+错误快速失败逻辑,我们换一种写法(返回新Promise手动控制状态):
const promiseAllAsyncAwait = function(iterable) { // 兼容数组或类数组参数 const args = Array.isArray(iterable) ? iterable : Array.from(arguments); const total = args.length; if (total === 0) return Promise.resolve([]); return new Promise((resolve, reject) => { const result = new Array(total); // 用索引保证结果顺序和输入一致 let completedCount = 0; args.forEach((item, index) => { // 把所有输入转换成Promise(支持非Promise值) Promise.resolve(item) .then(res => { result[index] = res; completedCount++; // 所有任务完成时返回结果 if (completedCount === total) { resolve(result); } }) .catch(err => { console.log(123); // 一旦有任务失败,立刻终止并返回错误 reject(err); }); }); }); }; // 测试代码不变 const asyncTask1 = new Promise((resolve) => setTimeout(() => resolve('Task 1'), 1000)); const asyncTask2 = new Promise((resolve, reject) => setTimeout(() => reject('Error in Task 2'), 500)); const asyncTask3 = new Promise((resolve) => setTimeout(() => resolve('Task 3'), 1500)); (async () => { try { const results = await promiseAllAsyncAwait([asyncTask1, asyncTask2, asyncTask3]); console.log(results); } catch (error) { console.error('Error in promiseAllAsync:', error); } })();
修复后的效果
- 所有Promise并行执行,
asyncTask2的reject会被立刻捕获,输出123。 - 整个
promiseAllAsyncAwait会立刻返回rejected状态的Promise,外面的try/catch会捕获到错误,输出Error in promiseAllAsync: Error in Task 2。 - 完全符合原生
Promise.all的行为:只要有一个Promise拒绝,就立刻终止并返回错误,不会等待其他任务完成。
备注:内容来源于stack exchange,提问作者123123123123
相关产品推荐
相关产品推荐

