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

Node.js中userdata.json无法存储数据,始终为空数组问题排查

Node.js数据写入userdata.json失败问题解决

问题描述

在Node.js项目中尝试将用户数据写入userdata.json文件时遇到异常:无论是否手动创建该文件,文件内容始终为[]。执行writeFile操作前的console.log能正常打印数据,但写入后文件无法保存正确的用户数据。相关代码如下(fetchAll函数可忽略):

原代码片段:

const fs = require('fs');
const path = require('path');

const p = path.join(
    path.dirname(require.main.filename),
    'data',
    'userdata.json'
);

module.exports=class userdata{
    constructor(username,phoneNo,mothersName,fathersName,address){
        this.username=username
        this.phoneNo=phoneNo
        this.fathersName=fathersName
        this.mothersName=mothersName
        this.address=address
    }
    save() {
        
        this.id = Math.random().toString();
        fs.readFile(p,(err,data)=>{
            let userData = []
            if(!err){
                userData=JSON.parse(data)
                console.log(userData)

            }
            userData.push(this)
            
            console.log("pushed")
        })
        
        fs.writeFile(p, JSON.stringify(userData),(err)=>{
            if(err){
            console.log(err)
           }
          })
        }
static fetchAll(){
        fs.readFile(p,(err,data)=>{
            if(err)
            return []
            return JSON.parse(data)
        }
        )
        
    }
}

问题根源

  1. 异步操作顺序错误:fs.readFile是异步函数,回调会在文件读取完成后执行,但原代码中fs.writeFile直接在readFile之后同步执行,此时readFile的回调还未触发,userData未被正确赋值为读取到的旧数据,写入的是未初始化的空数组。
  2. 变量作用域问题:userData定义在readFile的回调内部,外部的writeFile无法访问到回调内更新后的userData,只能访问到未定义的变量(或全局默认的空值)。

修复方案

将writeFile操作移至readFile的回调函数内部,确保在读取并更新完数据后再执行写入操作。也可以使用fs.promises结合async/await语法优化代码可读性。

修复后的回调版本代码

const fs = require('fs');
const path = require('path');

const p = path.join(
    path.dirname(require.main.filename),
    'data',
    'userdata.json'
);

module.exports = class UserData {
    constructor(username, phoneNo, mothersName, fathersName, address) {
        this.username = username;
        this.phoneNo = phoneNo;
        this.fathersName = fathersName;
        this.mothersName = mothersName;
        this.address = address;
    }

    save() {
        this.id = Math.random().toString();
        // 将writeFile移到readFile回调内,确保数据读取完成后再写入
        fs.readFile(p, (err, data) => {
            let userData = [];
            if (!err) {
                try {
                    userData = JSON.parse(data);
                } catch (parseErr) {
                    // 处理文件内容不是有效JSON的情况
                    console.log('解析JSON失败,使用空数组:', parseErr);
                    userData = [];
                }
            }
            userData.push(this);
            // 在此执行写入操作
            fs.writeFile(p, JSON.stringify(userData), (writeErr) => {
                if (writeErr) {
                    console.log('写入文件失败:', writeErr);
                } else {
                    console.log('数据保存成功');
                }
            });
        });
    }

    static fetchAll(callback) {
        // 原fetchAll无法直接返回异步结果,需改为回调方式
        fs.readFile(p, (err, data) => {
            if (err) {
                callback([]);
                return;
            }
            try {
                const userData = JSON.parse(data);
                callback(userData);
            } catch (parseErr) {
                console.log('解析JSON失败:', parseErr);
                callback([]);
            }
        });
    }
}

可选:async/await优化版本

使用fs.promises避免回调嵌套,代码逻辑更清晰:

const fs = require('fs').promises;
const path = require('path');

const p = path.join(
    path.dirname(require.main.filename),
    'data',
    'userdata.json'
);

module.exports = class UserData {
    constructor(username, phoneNo, mothersName, fathersName, address) {
        this.username = username;
        this.phoneNo = phoneNo;
        this.fathersName = fathersName;
        this.mothersName = mothersName;
        this.address = address;
    }

    async save() {
        this.id = Math.random().toString();
        let userData = [];
        try {
            const data = await fs.readFile(p);
            userData = JSON.parse(data);
        } catch (err) {
            // 文件不存在或读取失败,使用空数组
            console.log('读取文件失败,使用空数组:', err);
        }
        userData.push(this);
        try {
            await fs.writeFile(p, JSON.stringify(userData));
            console.log('数据保存成功');
        } catch (writeErr) {
            console.log('写入文件失败:', writeErr);
        }
    }

    static async fetchAll() {
        try {
            const data = await fs.readFile(p);
            return JSON.parse(data);
        } catch (err) {
            console.log('读取文件失败:', err);
            return [];
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 10:45:45