如何清除Express.js缓存,提供每秒更新的JSON文件服务?
问题描述
我正在编写一个程序,通过Express.js提供JSON格式的实时信息供另一程序使用,当前用于每秒上报CPU使用率。JSON文件本身更新正常,但Express.js始终缓存首个版本,无法返回最新内容。我已尝试删除require缓存、安装express-reload等方法,但均未解决问题。
现有循环代码(收集并提供数据)
setInterval(() => { Monitor.run() ServerInstance.serveData(require('../data.json')); }, 1000);
serveData函数实现
serveData (data) { this.app.get('/', (_request, response) => { response.setHeader('Content-Type', 'application/json'); response.json(data); }) }
补充尝试(使用fs.readFile)
我尝试使用fs.readFile获取最新数据并传给Express,控制台能输出正确的更新后数据,但Express仍返回程序启动时的首个数据,请问我忽略了什么关键点?
对应的代码:
fs.readFile(__dirname + '/../data.json', 'utf-8', (error, data) => { if (error) console.error(error); // 此处输出正确信息 console.log(data); // 但Express仍返回初始数据 ServerInstance.serveData(data); })
问题根源与解决方案
你的核心问题是重复调用app.get('/')注册路由,但Express只会保留第一个注册的路由处理函数。每次调用serveData时,你都在给根路径添加新的处理函数,但客户端请求时,Express只会执行第一个注册的那个,所以永远返回初始数据。
正确实现方式
不需要每次更新数据就重新注册路由,而是让路由处理函数在每次请求时主动获取最新数据:
方案1:路由触发时实时读取文件
初始化时只注册一次路由,每次请求触发时读取最新的JSON文件内容:
// 只在初始化时注册一次路由 this.app.get('/', (_request, response) => { response.setHeader('Content-Type', 'application/json'); fs.readFile(__dirname + '/../data.json', 'utf-8', (error, data) => { if (error) { console.error(error); return response.status(500).json({ error: '读取数据失败' }); } // 解析JSON字符串并返回 response.json(JSON.parse(data)); }); });
方案2:维护内存实时数据,路由直接返回
如果不想每次请求都读文件,可以在定时任务里更新内存变量,路由直接返回这个变量(性能更优):
// 初始化内存变量存储实时数据 let realtimeData = {}; // 定时任务更新内存数据 setInterval(() => { Monitor.run(); fs.readFile(__dirname + '/../data.json', 'utf-8', (error, data) => { if (!error) { realtimeData = JSON.parse(data); } }); }, 1000); // 只注册一次路由 this.app.get('/', (_request, response) => { response.setHeader('Content-Type', 'application/json'); response.json(realtimeData); });
为什么之前的方法无效?
- 使用
require('../data.json')时,Node.js会缓存模块内容,即使文件更新,require也不会自动重新读取,手动清缓存不是最优解。 - 多次调用
app.get('/')会添加多个路由处理函数,但Express匹配路由时会按注册顺序执行第一个匹配的函数,后续添加的处理函数永远不会被触发,所以不管传入什么新data,返回的都是第一个注册函数里的初始数据。
内容的提问来源于stack exchange,提问作者cmrxnn
相关产品推荐
相关产品推荐

