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.
嗯,这改变了一切。你应该在原来的问题中证明这一点。如果是这种情况,那么您必须对循环中的每个文件进行排序,以便它在前进到下一个之前完成一个。为防止写入同一文件之间发生冲突,您必须确保两件事:
- 您对循环中的每个文件进行排序,以便下一个文件在前一个文件完成之前不会开始。
- 您不要在该代码仍在运行时再次调用它。
您可以像这样确保第一项:
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
,而该函数是 运行。
我需要根据由传递给自定义 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.
嗯,这改变了一切。你应该在原来的问题中证明这一点。如果是这种情况,那么您必须对循环中的每个文件进行排序,以便它在前进到下一个之前完成一个。为防止写入同一文件之间发生冲突,您必须确保两件事:
- 您对循环中的每个文件进行排序,以便下一个文件在前一个文件完成之前不会开始。
- 您不要在该代码仍在运行时再次调用它。
您可以像这样确保第一项:
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
,而该函数是 运行。