如何用回调机制在嵌套for循环完成后返回result数组?
问题描述
现有如下代码:
const result = []; for(i=0; i < 5; i++){ for(j=0; j<3; j++){ s3Service.getS3Content(key, bucket, (err, res)=>{ if(err){ console.log("error occurred !"); result.push({msg:`error occurred for ${key}`}) } if(res){ result.push(res); } }) } }
如何在所有内外循环迭代完成后返回result?
我知道通过promise...then或async...await可以轻松解决,但出于某些原因,我希望仅通过回调机制实现。有没有简便的回调写法?
附s3Service.js代码:
const getS3Content = (key, bucketName, cb) => { S3.getObject({ Bucket: bucketName, Key: key }, (err, result) => { if (err) { console.log("error occured in getS3Content", err); cb(err); } if (result) { cb(null, result); } }) }
回调实现方案
可以通过计数器跟踪异步任务完成状态的方式实现,核心思路是统计所有异步请求的总数,每完成一个请求就将计数器加1,当计数器等于总请求数时,触发最终的回调返回结果。
修改后的代码示例
const result = []; // 计算总异步任务数:5次外循环 × 3次内循环 const totalTasks = 5 * 3; let completedTasks = 0; // 定义所有任务完成后的回调函数,用于处理最终结果 function handleFinalResult() { // 此处可根据需求返回或处理result,比如传递给上层逻辑 console.log("所有请求完成", result); } // 循环添加异步任务,注意用let声明循环变量避免闭包污染 for(let i=0; i < 5; i++){ for(let j=0; j<3; j++){ s3Service.getS3Content(key, bucket, (err, res)=>{ if(err){ console.log("error occurred !"); result.push({msg:`error occurred for ${key}`}); } else if(res){ result.push(res); } // 每完成一个请求,计数器加1 completedTasks++; // 检查是否所有任务都已完成 if(completedTasks === totalTasks) { handleFinalResult(); } }) } }
补充优化建议
原s3Service.getS3Content存在重复调用回调的风险(当err存在时,调用cb(err)后仍会执行if(result)分支),建议修改为:
const getS3Content = (key, bucketName, cb) => { S3.getObject({ Bucket: bucketName, Key: key }, (err, result) => { if (err) { console.log("error occured in getS3Content", err); return cb(err); // 加return终止后续逻辑,避免重复调用回调 } cb(null, result); // err不存在时直接返回结果 }) }
内容的提问来源于stack exchange,提问作者micronyks
相关产品推荐
相关产品推荐

