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) } ) } }
问题根源
- 异步操作顺序错误:
fs.readFile是异步函数,回调会在文件读取完成后执行,但原代码中fs.writeFile直接在readFile之后同步执行,此时readFile的回调还未触发,userData未被正确赋值为读取到的旧数据,写入的是未初始化的空数组。 - 变量作用域问题:
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
相关产品推荐
相关产品推荐

