Node.js如何将fs.readFile读取的文件数据存入内存并解决异步取值问题
Node.js 读取文件数据的内存复用问题解决方案
为什么回调外读取变量会得到undefined
- 这个现象是JavaScript单线程事件循环、Node.js异步非阻塞IO的核心运行特性直接导致的,不是语法bug
fs.readFile属于非阻塞IO方法:调用该方法时,Node.js会把文件读取操作交给底层操作系统处理,本身不会等待读取完成,会立刻向下执行后续同步代码- 代码中写的
//fs.readFile is done by now..属于典型的流程认知错位:执行到这行注释时,文件IO操作根本没有完成,对应的读取回调函数还没被事件循环触发 - 代码实际执行顺序是:初始化
somedata为空值→触发异步文件读取→立刻执行console.log(somedata)→过一段时间等文件读取完成后,才会执行回调给somedata赋值,因此日志打印的永远是读取完成前的初始值。
内存复用的正确实现方式
完全不需要“读取后写临时文件再重新读取”的冗余操作,直接把读取到的值存在内存对象里复用即可,常用实现方案如下:
- 基础方案:把所有依赖读取数据的业务逻辑,直接放到
fs.readFile的回调内部执行,确保数据赋值完成后再触发后续操作let somedata = ''; fs.readFile('somefile', 'utf8', (err, data) => { if (err) throw err; somedata = data; // 以下业务逻辑在数据赋值完成后执行,可正常获取内存中的数据 processNumericDataset(somedata); pushToCalculationPipeline(somedata); }); - 定时刷新内存缓存方案:如果需要定期读取文件更新内存值,可以封装统一的内存缓存模块,全局业务直接从缓存取数,无需重复写IO逻辑
const fs = require('fs'); // 全局内存缓存对象 const numericDataCache = { rawData: null, targetFilePath: 'somefile', // 重新读取文件刷新内存值 async refreshCache() { this.rawData = await fs.promises.readFile(this.targetFilePath, 'utf8'); }, // 启动定时刷新任务 startAutoRefresh(interval = 60000) { // 启动应用时先加载一次初始数据 this.refreshCache(); // 按固定间隔读取文件更新内存 setInterval(() => this.refreshCache(), interval); } }; // 应用初始化时启动缓存,其他业务函数直接读取`numericDataCache.rawData`即可获取内存中的最新值 numericDataCache.startAutoRefresh(30000); - 可读性优化方案:如果要避免多层回调嵌套,可以使用Node.js原生提供的Promise化fsAPI,配合async/await把异步逻辑写成同步书写风格
const fs = require('fs/promises'); let somedata = ''; async function bootstrapApp() { // 等待文件读取完成、赋值完成后再执行后续逻辑 somedata = await fs.readFile('somefile', 'utf8'); console.log(somedata); startDataProcessingService(); } bootstrapApp();
实用提示:处理大规模数值数据时,不建议将文件内容以字符串形式长期存在内存中,可以读取完成后直接将Buffer转换为Float64Array等二进制数值结构存储,能大幅降低内存占用、提升数据运算效率。
内容的提问来源于stack exchange,提问作者gorilla bull
相关产品推荐
相关产品推荐

