Nodejs用fs writefile写多个动态变化的文件

Nodejs write multiple dynamically changing files with fs writefile

我需要根据由传递给自定义 writeData() 函数的对象组成的数组编写多个动态变化的文件。该数组由包含文件名和要写入的数据的对象组成,如下所示:

[
  {
    file_name: "example.json",
    dataObj,
  },
  {
    file_name: "example2.json",
    dataObj,
  },
  {
    file_name: "example3.json",
    dataObj,
  },
  {
    file_name: "example4.json",
    dataObj,
  },
];

我目前的方法是映射这个数组并读取+写入新数据到每个文件:

array.map((entry) => {
  fs.readFile(
    entry.file_name,
    "utf8",
    (err, unparsedData) => {
      if (err) console.log(err);
      else {
        var parsedData = JSON.parse(unparsedData);
        parsedData.data.push(entry.dataObj);
        const parsedDataJSON = JSON.stringify(parsedData, null, 2);
        fs.writeFile(
          entry.file_name,
          parsedDataJSON,
          "utf8",
          (err) => {
            if (err) console.log(err);
          }
        );
      }
    }
  );
});

然而,这不起作用。只有一小部分数据被写入这些文件,而且文件经常没有以 json 格式正确写入(我认为这是因为两个 writeFile 进程同时写入同一个文件并且破坏了文件) .显然这并没有像我预期的那样工作。

我试图解决这个问题的多种方法包括尝试使 fs.writeFile 同步(延迟映射循环,允许每个进程在移动到下一个条目之前完成),但这不是一个很好的做法,因为同步进程会挂起整个应用程序。我也研究过实现承诺,但无济于事。我是 nodejs 的新手,很抱歉错过 details/information。感谢您的帮助!

The same file is often listed multiple times in the array if that changes anything.

嗯,这改变了一切。你应该在原来的问题中证明这一点。如果是这种情况,那么您必须对循环中的每个文件进行排序,以便它在前进到下一个之前完成一个。为防止写入同一文件之间发生冲突,您必须确保两件事:

  1. 您对循环中的每个文件进行排序,以便下一个文件在前一个文件完成之前不会开始。
  2. 您不要在该代码仍在运行时再次调用它。

您可以像这样确保第一项:

async function processFiles(array) {
    for (let entry of array) {
        const unparsedData = await fs.promises.readFile(entry.file_name, "utf8");
        const parsedData = JSON.parse(unparsedData);
        parsedData.data.push(entry.dataObj);
        const json = JSON.stringify(parsedData, null, 2);
        await fs.promise.writeFile(entry.file_name, json, "utf8");
    }
}

如果其中任何一个出错,这将中止循环。如果你想让它继续写其他的,你可以在内部添加一个try/catch

async function processFiles(array) {
    let firstError;
    for (let entry of array) {
        try {
            const unparsedData = await fs.promises.readFile(entry.file_name, "utf8");
            const parsedData = JSON.parse(unparsedData);
            parsedData.data.push(entry.dataObj);
            const json = JSON.stringify(parsedData, null, 2);
            await fs.promise.writeFile(entry.file_name, json, "utf8");
        } catch (e) {
            // log error and continue with the rest of the loop
            if (!firstError) {
                firstError = e;
            }
            console.log(e);
        }
    }
    // make sure we communicate back any error that happened
    if (firstError) {
        throw firstError;
    }
}

为了确保以上第二点,您将不得不要么不使用 setInterval()(将其替换为您在 processFiles() 解决的承诺时设置的 setTimeout()或者绝对确保 setInterval() 时间足够长,它永远不会在 processFiles() 完成之前触发。


此外,请绝对确保您没有修改此函数中使用的 array,而该函数是 运行。