Node.js:实现批量异步请求,单个请求失败不阻塞后续执行
解决Node.js批量异步请求单批次失败不阻塞后续批次的问题
原代码的问题
forEach不支持异步等待,会立即执行所有回调,外层的try/catch无法捕获异步回调内部的错误——这些错误属于独立的Promise,未被捕获时会导致未处理的Promise拒绝,甚至可能终止Node.js进程。- 单个批次请求失败时,错误没有被内部捕获,会向外抛出,但由于异步回调脱离了外层
try的作用域,无法被捕获,也会出现未处理的错误提示。
解决方案
方案一:在每个批次请求内部捕获错误
直接在forEach的异步回调中加入try/catch,让单个批次的失败独立处理,不影响其他批次执行:
const chunks = [["+1-321341321", "1-3213213213"], ["+1-3213321321","+1-3213413213241"]]; chunks.forEach(async (item) => { try { await axios.post('https://example.com/v1', { to: item.map(pn => ({ phone_number: pn.toString().trim() })) }); console.log(`批次处理成功: ${JSON.stringify(item)}`); } catch (e) { console.error(`批次处理失败: ${JSON.stringify(item)}`, e.message); } });
方案二:用Promise.allSettled统一处理所有批次
如果需要等待所有批次完成并获取每个批次的执行结果,用map生成Promise数组,再通过Promise.allSettled处理:
const chunks = [["+1-321341321", "1-3213213213"], ["+1-3213321321","+1-3213413213241"]]; async function processChunks() { const batchPromises = chunks.map(async (item) => { try { const response = await axios.post('https://example.com/v1', { to: item.map(pn => ({ phone_number: pn.toString().trim() })) }); return { status: 'success', batch: item, responseData: response.data }; } catch (e) { return { status: 'failed', batch: item, errorMsg: e.message }; } }); const results = await Promise.allSettled(batchPromises); results.forEach((result, index) => { if (result.status === 'fulfilled') { console.log(`批次 ${index + 1} ${result.value.status}:`, result.value.batch); } else { console.error(`批次 ${index + 1} ${result.reason.status}:`, result.reason.batch, result.reason.errorMsg); } }); } processChunks();
优化:提前过滤无效号码
为减少请求失败概率,可提前过滤每个批次中不符合格式(不以+开头)的号码,再发起请求:
const chunks = [["+1-321341321", "1-3213213213"], ["+1-3213321321","+1-3213413213241"]]; const filteredChunks = chunks.map(batch => batch.filter(phone => phone.toString().trim().startsWith('+')) ); async function processFilteredChunks() { const batchPromises = filteredChunks.map(async (item) => { if (item.length === 0) { return { status: 'skipped', batch: item, msg: '批次无有效号码,跳过请求' }; } try { const response = await axios.post('https://example.com/v1', { to: item.map(pn => ({ phone_number: pn.toString().trim() })) }); return { status: 'success', batch: item, responseData: response.data }; } catch (e) { return { status: 'failed', batch: item, errorMsg: e.message }; } }); const results = await Promise.allSettled(batchPromises); results.forEach((result, index) => { if (result.status === 'fulfilled') { console.log(`批次 ${index + 1}:`, result.value); } else { console.error(`批次 ${index + 1} 处理异常:`, result.reason); } }); } processFilteredChunks();
内容的提问来源于stack exchange,提问作者Obaid Aqeel
相关产品推荐
相关产品推荐

