You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:54:03