Node.js中如何通过Promise.all实现循环多API调用的统一结果返回
问题修复:批量API调用的Promise异步控制
你的代码核心问题是没正确利用Promise.all实现批量异步控制,且错误处理逻辑不符合Promise的失败触发规则,无法实现「全成功才返回、一个失败就报错」的需求。以下是具体修正方案:
关键问题点
getChunkUploadResponse$错误处理逻辑错误:你用resolve返回错误信息,但Promise.all仅在Promise被reject时才判定操作失败,错误场景必须用reject抛出异常。- 未收集Promise到数组:声明了
promiseAll但未将getChunkUploadResponse$的返回值存入,导致Promise.all完全未生效。 - 过早触发resolve:
getChunkBatchDetailsResponse$在request回调末尾直接resolve(batchMessage),未等待所有分片上传完成就返回结果。 - 回调式request未Promise化:内部request调用为回调风格,未用Promise包裹,导致异步流程失控。
修正后的完整代码
1. 修复分片上传的Promise函数
function getChunkUploadResponse$(id, directory, buffer, userToken) { return new Promise((resolve, reject) => { // 新增reject参数用于抛出错误 request.post( `${configJSON.apigeeBaseUrl}/UploadChunk`, { formData: { file: { value: buffer, options: { filename: `${directory.name}.zip`, }, }, }, headers: { Authorization: `Bearer ${userToken}`, }, }, (err, response) => { logMessage('err performing batch chunk upload:', JSON.stringify(err)); logMessage('response performing batch chunk upload:', JSON.stringify(response)); if (err) { // 错误场景用reject抛出,触发Promise.all的失败逻辑 reject({ id, directory: directory.path, message: err.message, code: 500, }); return; } const statusCode = response.statusCode; const batchMessage = { // 用局部变量替代this,避免上下文混乱 id, directory: directory.path, message: response.statusMessage, code: statusCode, }; if (statusCode === 201) { try { batchMessage.batch = JSON.parse(response.body); logMessage('Successfully performed a batch chunk upload'); resolve(batchMessage); } catch (parseErr) { // JSON解析失败也视为错误抛出 reject({ id, directory: directory.path, message: `Failed to parse response: ${parseErr.message}`, code: 500, }); } } else if (statusCode === 413) { try { reject({ id, directory: directory.path, message: JSON.parse(response.body), code: 413, }); } catch (parseErr) { reject({ id, directory: directory.path, message: 'Payload too large', code: 413, }); } } else { let message = response.statusMessage; try { message = JSON.parse(response.body); } catch {} batchMessage.message = message; // 非201状态码均视为失败,用reject抛出 reject(batchMessage); } }, ); }); }
2. 修复批量处理的主函数
function getChunkBatchDetailsResponse$(id, baseUri, formData, totalFileSize, chunkSize, userToken) { return new Promise((resolve, reject) => { const options = { method: 'POST', url: `${configJSON.apigeeBaseUrl}/batch`, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${userToken}`, }, body: {} // 补充你的请求body内容 }; request(options, (error, response) => { if (error) { reject({ id, message: error.message, code: 500 }); return; } if (!response.body) { reject({ id, message: 'Empty response from batch API', code: 400 }); return; } // 分片切割逻辑优化 const chunksArray = []; let chunkStart = 0; let chunkEnd = chunkSize; const totalNumberOfChunks = Math.ceil(totalFileSize / chunkSize); for (let i = 0; i < totalNumberOfChunks; i++) { chunkEnd = Math.min(chunkStart + chunkSize, totalFileSize); chunksArray.push(formData.buffer.subarray(chunkStart, chunkEnd)); chunkStart = chunkEnd; } // 收集所有分片上传的Promise const promiseAll = chunksArray.map((chunkBuffer, index) => { const chunkNumber = index + 1; logMessage(`Starting upload for chunk ${chunkNumber} of ${totalNumberOfChunks}`); // 传入必要参数(directory需根据实际业务场景补充) return getChunkUploadResponse$(id, directory, chunkBuffer, userToken); }); // 用Promise.all等待所有分片上传完成 Promise.all(promiseAll) .then((allResults) => { // 所有上传成功,返回汇总结果 resolve({ id, message: 'All chunks uploaded successfully', results: allResults }); }) .catch((error) => { // 任意分片失败,直接返回错误 reject(error); }); }); }); }
核心规则说明
Promise.all特性:仅当所有传入的Promise都resolve时,才会返回所有结果的数组;只要有一个Promisereject,就会立即抛出该错误。- 错误处理必须用reject:不要用
resolve返回错误对象,否则Promise.all会将其视为成功结果。 - 异步流程需串行等待:必须等所有异步操作完成后,再调用
resolve或reject,禁止提前触发。
内容的提问来源于stack exchange,提问作者vijred
相关产品推荐
相关产品推荐

