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

使用forEach迭代对象写入JSON文件时仅最后一个对象生效的问题及解决方法

问题分析与解决方案

这个问题的核心是异步操作的并发冲突,我来帮你拆解清楚:

你用array.forEach()遍历数组时,会立刻触发所有writeTheData函数的调用,但fs.readFile是异步方法——这意味着所有的读取操作几乎同时启动,它们读到的都是fb.json的原始内容(还没有任何修改的版本)。

每个函数实例都会基于这份原始数据修改出自己的newsData,然后依次执行写入。后面的写入操作会直接覆盖前面的,因为前面的修改还没来得及保存到文件里,后面的就已经基于原始数据完成修改并写入了。这就是为什么最后只有最后一个对象被保留下来——它是最后一个完成写入的,覆盖了之前所有的修改。

虽然你用obj.link作为唯一键,但这解决的是对象本身的覆盖问题,解决不了异步并发读写带来的文件内容覆盖。


修复方案(两种推荐方式)

方案1:串行处理异步操作(逐个执行)

把writeTheData改成异步函数,用async/await确保每次读写完成后再处理下一个对象,彻底避免并发冲突。

首先切换到Promise版的fs模块:

const fs = require('fs').promises;

然后修改你的函数:

async function writeTheData(obj) {
  try {
    // 异步读取文件,等待读取完成
    const data = await fs.readFile('./assets/data/fb.json');
    let newsData = JSON.parse(data);
    
    // 更新数据
    newsData[obj.link] = { 
      ...newsData[obj.link], 
      link: obj.link, 
      title: obj.title, 
      text: obj.contentSnippet, 
      articleDate: obj.pubDate, 
      content: obj.content 
    };
    
    // 异步写入文件,等待写入完成
    await fs.writeFile("./assets/data/fb.json", JSON.stringify(newsData));
    console.log(`Successfully wrote data for: ${obj.title}`);
  } catch (err) {
    console.error('Error processing data:', err);
  }
}

调用时不要用forEach(它不支持异步等待),改用for...of循环:

(async () => {
  for (const obj of arr) {
    await writeTheData(obj);
  }
})();

方案2:批量处理(更高效)

既然你要处理整个数组,不如只读取一次文件,在内存中完成所有数据更新,最后一次性写入——这样既避免了异步冲突,也减少了IO操作次数,效率更高。

代码示例:

const fs = require('fs').promises;

async function writeAllData(arr) {
  try {
    // 只读取一次文件
    const data = await fs.readFile('./assets/data/fb.json');
    let newsData = JSON.parse(data);
    
    // 批量更新所有数据
    arr.forEach(obj => {
      newsData[obj.link] = { 
        ...newsData[obj.link], 
        link: obj.link, 
        title: obj.title, 
        text: obj.contentSnippet, 
        articleDate: obj.pubDate, 
        content: obj.content 
      };
    });
    
    // 一次性写入所有修改
    await fs.writeFile("./assets/data/fb.json", JSON.stringify(newsData));
    console.log('All 16 items have been written successfully!');
  } catch (err) {
    console.error('Error processing batch data:', err);
  }
}

// 调用批量处理函数
writeAllData(arr);

这个方案是最优的,因为它只涉及一次读和一次写操作,完全规避了异步并发的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 03:04:07