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

Node.js中如何高效处理50万份JSON文件的数值累加任务?

处理大规模JSON文件读取的Node.js方案

问题核心

你当前的矛盾点在于:一次性异步读取50万个文件会触发「too many files open」错误(系统同时打开的文件描述符数量有限);而同步读取又会因为阻塞I/O导致速度极慢。本质原因是直接用forEach发起所有异步请求,会瞬间创建大量文件句柄,超出系统限制。

可行方案

1. 分批异步处理(新手友好)

把文件数组拆分成若干小批次,每批处理完成后再启动下一批,从根源上控制同时打开的文件数量。

2. 控制并发数(更灵活)

用工具限制同时执行的异步任务数量,无需手动分批次,适合复杂场景下的动态调整。

代码示例

分批处理实现(原生Node.js)

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

// 单个文件处理:读取JSON并返回目标数值
async function processFile(filePath) {
  try {
    const data = await fs.readFile(filePath, 'utf8');
    const jsonData = JSON.parse(data);
    // 替换成你需要累加的字段名
    return jsonData.targetNumber || 0;
  } catch (err) {
    console.error(`处理文件 ${filePath} 失败:${err.message}`);
    return 0; // 出错文件按0处理,不中断整体流程
  }
}

// 分批处理主函数
async function processFilesInBatches(filePaths, batchSize = 100) {
  let totalSum = 0;
  const totalFiles = filePaths.length;

  for (let i = 0; i < totalFiles; i += batchSize) {
    // 截取当前批次的文件路径
    const currentBatch = filePaths.slice(i, i + batchSize);
    // 并行处理当前批次所有文件
    const batchResults = await Promise.all(currentBatch.map(processFile));
    // 累加当前批次结果
    batchResults.forEach(num => totalSum += num);
    // 进度提示
    console.log(`已完成 ${Math.min(i + batchSize, totalFiles)}/${totalFiles} 个文件,当前总和:${totalSum}`);
  }

  console.log('所有文件处理完成,最终总和:', totalSum);
  return totalSum;
}

// 调用示例:batchSize可根据系统调整(建议100-200)
processFilesInBatches(filePaths, 100);

控制并发数实现(用第三方库p-limit)

如果不想手动分批次,可以用p-limit库直接控制并发数:

npm install p-limit
const fs = require('fs').promises;
const pLimit = require('p-limit');

// 限制同时执行100个异步任务
const limit = pLimit(100);

async function processFile(filePath) {
  try {
    const data = await fs.readFile(filePath, 'utf8');
    const jsonData = JSON.parse(data);
    return jsonData.targetNumber || 0;
  } catch (err) {
    console.error(`处理文件 ${filePath} 失败:${err.message}`);
    return 0;
  }
}

async function processFilesWithConcurrency(filePaths) {
  let totalSum = 0;
  // 生成带并发限制的任务数组
  const tasks = filePaths.map(filePath => limit(async () => {
    const num = await processFile(filePath);
    totalSum += num;
  }));
  // 等待所有任务完成
  await Promise.all(tasks);
  console.log('最终总和:', totalSum);
  return totalSum;
}

// 调用示例
processFilesWithConcurrency(filePaths);

关键注意事项

  • 调整并发/批次大小:根据你的系统配置调整batchSize或并发数(一般100-200比较安全,系统默认文件描述符限制通常是1024)。
  • 错误处理:一定要给单个文件处理加try/catch,避免某个文件读取或解析错误导致整个任务中断。
  • 内存占用:每个文件20-100KB,100个并发的话内存占用约2-10MB,完全在Node.js承受范围内。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:42:41