ES6循环内修改的变量跳出循环后回到初始值,函数总返回[0,0]是什么原因
根本原因
你的代码问题出在异步函数的执行时序和返回值传递逻辑错误:
readdir是Node.js内置的异步I/O方法,你传入的回调函数不会在调用readdir后立刻执行,会被暂存到事件循环队列,等主线程所有同步代码执行完成后才会触发执行。你写在末尾的return Array(cb.count, cb.user)是同步执行逻辑,执行时readdir的回调还没有运行,count和user还保持初始的0值,所以永远返回[0, 0]。- 你在
readdir回调里写的return [-1, -1]也无法传递到外层getMonthSubs函数,这个返回值只会被readdir的内部逻辑接收,外层完全拿不到。
解决方案
方案1:改用同步读取逻辑(简单快速,适合小体量日志文件场景)
直接把异步的readdir换成同步的readdirSync,全流程同步执行就不会出现时序问题:
function getMonthSubs(month) { var cb = {count: 0, user: 0}, userTemp = []; try { // 改用同步readdirSync,直接拿到返回的files数组 const files = readdirSync('./log/' + month, 'utf-8'); for (let j = 0; j < files.length; j++) { let temp = JSON.parse(readFileSync('./log/' + month + '/' + files[j], 'utf-8')); for (var key in temp) { cb.count += temp[key].length; if (!userTemp.includes(key)) { userTemp.push(key); cb.user++; } } } return [cb.count, cb.user]; } catch (err) { // 同步方法用try/catch捕获错误 return [-1, -1]; } }
方案2:用Promise+async/await封装异步逻辑(性能更好,适合大文件/高并发场景)
如果要保留异步的性能优势,可以封装成Promise,调用时用await取值:
// 封装成返回Promise的函数 function getMonthSubs(month) { return new Promise((resolve, reject) => { var cb = {count: 0, user: 0}, userTemp = []; readdir('./log/' + month, 'utf-8', function (err, files) { if (err) return resolve([-1, -1]); for (let j = 0; j < files.length; j++) { let temp = JSON.parse(readFileSync('./log/' + month + '/' + files[j], 'utf-8')); for (var key in temp) { cb.count += temp[key].length; if (!userTemp.includes(key)) { userTemp.push(key); cb.user++; } } } resolve([cb.count, cb.user]); }); }) } // 调用方式:在async函数内用await接收返回值 async function test() { const res = await getMonthSubs('2021_11'); console.log(res); // 能拿到正确的统计值 }
内容的提问来源于stack exchange,提问作者Anotia
相关产品推荐
相关产品推荐

