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

Node.js如何检测JSON文件变更并读取更新后的内容?

问题原因

require() 加载JSON文件时自带全局缓存逻辑:第一次成功加载文件后,后续所有指向同一路径的require()调用都会直接返回内存中缓存的首次加载结果,不会重新访问磁盘读取文件。之前不管是事件回调里重复require还是无限循环require都拿不到新值,就是这个缓存机制导致的。

实现方案
  • 方案一:清除require缓存后重新加载(仅适合快速验证,不推荐生产用)
    每次调用require前,先把对应文件的缓存从require.cache对象中删除即可,注意缓存的键是文件的绝对路径,传相对路径会导致清缓存失败:

    const path = require('path')
    const jsonAbsPath = path.resolve(__dirname, './jsonfile.json')
    
    // 事件回调逻辑
    delete require.cache[jsonAbsPath]
    const jsonData = require(jsonAbsPath)
    console.log(jsonData.variable)
    

    这个方案缺陷很明显:如果外部程序还没写完JSON文件时刚好触发读取,会读到半写入的损坏内容直接抛错;另外路径处理稍有问题就会清缓存失败,稳定性差。

  • 方案二:用内置fs模块直接读取文件(适合按需读取的场景,稳定性高)
    绕开require的缓存逻辑,每次需要取值时直接通过fs模块读取磁盘上的文件内容,手动解析JSON:

    const fs = require('fs/promises')
    const path = require('path')
    const jsonAbsPath = path.resolve(__dirname, './jsonfile.json')
    
    async function getJsonVariable() {
      // 直接读取磁盘上的最新文件内容
      const fileContent = await fs.readFile(jsonAbsPath, 'utf-8')
      const jsonData = JSON.parse(fileContent)
      return jsonData.variable
    }
    
    // 事件触发时调用即可
    eventHandle(() => {
      getJsonVariable().then(val => console.log(val))
    })
    

    如果怕读到半写入的损坏文件,可以加个简单的重试逻辑,JSON解析失败时等待50-100ms再重新读取即可。

  • 方案三:监听文件变更自动更新内存值(适合需要实时感知变更的场景,性能最好)
    用Node.js内置的fs.watch方法监听目标JSON文件的修改事件,文件发生变化时自动读取最新内容更新到内存变量中,业务逻辑直接读内存变量即可,不需要每次触发事件都访问磁盘:

    const fs = require('fs')
    const path = require('path')
    const jsonAbsPath = path.resolve(__dirname, './jsonfile.json')
    
    // 存储最新JSON值的内存变量
    let latestJsonData = {}
    let reloadTimer = null
    
    // 统一的加载文件方法
    function reloadJson() {
      try {
        const content = fs.readFileSync(jsonAbsPath, 'utf-8')
        latestJsonData = JSON.parse(content)
      } catch (err) {
        console.error('JSON文件加载失败,大概率是文件正在写入:', err.message)
      }
    }
    
    // 初始化时第一次加载
    reloadJson()
    // 监听文件变化,加防抖避免重复触发,同时延迟100ms读取等文件写完
    fs.watch(jsonAbsPath, () => {
      clearTimeout(reloadTimer)
      reloadTimer = setTimeout(reloadJson, 100)
    })
    
    // 业务事件回调里直接读内存值即可
    eventHandle(() => {
      console.log(latestJsonData.variable)
    })
    

    注意:不同操作系统下fs.watch的触发逻辑有细微差异,极端场景可能出现漏触发的问题,生产环境可以加个间隔几秒的轮询兜底,定期校验文件内容,避免监听失效导致长期读到旧值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:12:32