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

JavaScript中使用fs.readFile后数组变为空的问题求助

问题分析与解决方案

问题代码

const fs = require('fs');
var students = [];
var programs = [];

module.exports.initialize = function(){
    return new Promise((resolve, reject) => {
        fs.readFile('./data/students.json', 'utf8',(err,data)=>{
            if(err) reject("Unable to read student data");
            students = JSON.parse(data);
        });
        console.log(students);
        fs.readFile('./data/programs.json', 'utf8',(err,data)=>{
            if(err) reject("Unable to read programs data");
            programs = JSON.parse(data);
        });
        console.log(programs);
        resolve("Both data read successfully");
    })
}

问题原因

核心是异步执行顺序问题:

  • fs.readFile是异步非阻塞API,调用后会直接继续执行后续代码,不会等待文件读取完成。
  • 你在调用fs.readFile后立刻执行console.log(students)和resolve,这时候文件还没读完,students和programs还是初始的空数组。
  • 而readFile的回调函数是在文件读取完成后才执行的,所以回调内赋值后打印数组会有值,但此时外部的console.log和resolve早就执行完了。

修复方案

使用Promise.all等待两个文件读取操作都完成后,再进行赋值和后续逻辑,同时推荐使用Node.js提供的Promise版fs模块(fs.promises)来简化代码:

方案1:使用fs.promises(推荐)

const fs = require('fs').promises;
var students = [];
var programs = [];

module.exports.initialize = function(){
    return Promise.all([
        fs.readFile('./data/students.json', 'utf8'),
        fs.readFile('./data/programs.json', 'utf8')
    ])
    .then(([studentData, programData]) => {
        students = JSON.parse(studentData);
        programs = JSON.parse(programData);
        console.log(students);
        console.log(programs);
        return "Both data read successfully";
    })
    .catch(err => {
        // 根据错误信息判断是哪个文件读取失败
        const errorMsg = err.path.includes('students') 
            ? "Unable to read student data" 
            : "Unable to read programs data";
        throw new Error(errorMsg);
    });
}

方案2:手动封装readFile为Promise

如果不想用fs.promises,可以手动把fs.readFile封装成Promise:

const fs = require('fs');
var students = [];
var programs = [];

// 封装异步读取为Promise
const readFile = (filePath, errorMsg) => {
    return new Promise((resolve, reject) => {
        fs.readFile(filePath, 'utf8', (err, data) => {
            if (err) reject(new Error(errorMsg));
            resolve(data);
        });
    });
};

module.exports.initialize = function(){
    return Promise.all([
        readFile('./data/students.json', "Unable to read student data"),
        readFile('./data/programs.json', "Unable to read programs data")
    ])
    .then(([studentData, programData]) => {
        students = JSON.parse(studentData);
        programs = JSON.parse(programData);
        console.log(students);
        console.log(programs);
        return "Both data read successfully";
    });
}

关键说明

  • Promise.all会等待所有传入的Promise都完成后才进入then回调,确保两个文件的数据都读取完成后再赋值。
  • 错误处理集中在catch里,避免了原代码中多次调用reject可能导致的Promise重复拒绝问题。

内容的提问来源于stack exchange,提问作者frowit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:45:31