Node.js更新JSON后报link属性读取错误的免重启修复方案
问题根因
报错和必须重启才能读到新内容的问题,本质是require()的加载机制导致的:
- Node.js会对所有通过
require()引入的模块、JSON文件做持久缓存,第一次加载完成后内容就存在内存中,后续调用直接读缓存,根本不会重新读取磁盘上更新后的文件 - 如果你更新JSON时用的是覆盖写入逻辑,写入瞬间文件可能处于不完整状态,或者你调整了JSON内的键值对,缓存内容和磁盘实际文件不匹配,就会抛出读不到
link属性的错误
可行方案
根据你的业务场景选就行,都不需要重启进程:
方案1:改动最小,清除require缓存后重新加载
不用改现有业务逻辑,只需要在读取sources前删掉对应缓存,强制Node重新从磁盘拉取最新文件即可:// 提前拿到JSON文件的绝对路径,注意要补全.json后缀 const sourcesPath = require.resolve('../folder/sources.json') // 每次读取前清缓存 delete require.cache[sourcesPath] const sources = require(sourcesPath) // *记得加可选链容错,避免传入不存在的number时直接崩溃* const source = sources[number]?.link这个方案适合JSON体积小、读取频率不高的场景,缺点是每次读取都要走磁盘IO,高频调用会有不必要的性能损耗。
方案2:用fs模块读取解析,灵活度更高
放弃用require()加载JSON,改用Node内置的fs模块直接读文件内容、手动解析,适配更复杂的场景:const fs = require('fs') const path = require('path') // 提前拼接JSON文件的绝对路径,避免相对路径运行时出错 const sourcesPath = path.join(__dirname, '../folder/sources.json') function getSources() { try { // 同步读取文件内容,指定编码拿到字符串 const fileContent = fs.readFileSync(sourcesPath, 'utf-8') return JSON.parse(fileContent) } catch (err) { console.error('读取sources.json失败,请检查文件格式', err) // 出错时返回空对象,避免业务代码崩溃 return {} } } // 业务中调用 const sources = getSources() const source = sources[number]?.link如果你的bot读取这个配置的频率很高,可以加个文件监听,JSON更新时自动刷新内存里的配置,不用每次读都走磁盘:
const fs = require('fs') const path = require('path') const sourcesPath = path.join(__dirname, '../folder/sources.json') // 内存里常驻最新的配置 let sources = {} let refreshTimer = null // 初始化先加载一次 refreshSources() // 监听文件改动,自动刷新配置 fs.watch(sourcesPath, { persistent: false }, (eventType) => { if (eventType === 'change') { // 加100ms防抖,避免写入时多次触发导致读取半完成文件 clearTimeout(refreshTimer) refreshTimer = setTimeout(refreshSources, 100) } }) function refreshSources() { try { const content = fs.readFileSync(sourcesPath, 'utf-8') sources = JSON.parse(content) } catch (err) { console.error('sources.json更新失败,保留原有配置', err) } } // 业务代码直接读内存里的sources就行,永远是最新值 const source = sources[number]?.link这个方案性能最好,适合高频读取配置的场景,一定要做好JSON解析错误的捕获,避免改JSON时写错格式直接把bot搞崩。
内容的提问来源于stack exchange,提问作者MegaMix_Craft
相关产品推荐
相关产品推荐

