如何在遍历一系列目录的循环中使用异步 readdir 函数?
Posted
技术标签:
【中文标题】如何在遍历一系列目录的循环中使用异步 readdir 函数?【英文标题】:How to use async readdir function inside a loop iterating over series of directories? 【发布时间】:2021-01-13 09:46:16 【问题描述】:我正在归档来自多个目录的某些文本文件。因此,首先,我在一个文件夹中进行迭代,该文件夹为我提供了 folderPath,这个 folderPath 可以包含许多文件(txt、pdf 等)并且有多个文件夹路径,我对 folderPath 使用异步 readdir 并将这些单独的文件附加到归档器,然后最后关闭。如果我在文件夹循环结束之前执行 archive.finalize ,它不会在 zip 中生成所需数量的 txt 文件,而只是生成初始文件,这是显而易见的。如果我将 archive.finalize 保留在第 2 行,则会向我抛出一个错误,如下所示的目录结构。有人可以在这方面提供帮助吗?
目录结构如下:
主文件夹/文件夹1 主文件夹/文件夹2
mainfolder/folder1/sometext.txt mainfolder/folder1/someanothertext.txt
mainfolder/folder2/sometext.txt mainfolder/folder2/someanothertext.txt
现在我想把它压缩成:
Outuput.zip,其中包含 -> folder1 和 folder2 以及各自的 txt 文件。当使用同步功能到readdir(readdirsync)时,我能够实现它, 但是使用异步,我面临一些回调问题。
错误:
ArchiverError: queue closed
at Archiver.file (C:\Users\Workspace\code\node_modules\archiver\lib\core.js:692:24)
at C:\Users\Workspace\current_code_snippet
at Array.forEach (<anonymous>)
at C:\Users\current_code_snippet_ line 3 as specified in code snippet
at FSReqCallback.oncomplete (fs.js:156:23)
code: 'QUEUECLOSED',
data: undefined
代码:
this.children.forEach((value, _index, _array) =>
const folderPath = path.join(basePath, value);
fs.readdir(folderPath, (err, fileNames) =>
if (err)
throw err;
else
fileNames.forEach(file => // line 3
if (outputType === ".txt")
const filePath = path.join(basePath, value, file);
archive.file(filePath, name: `$value/$file` ); // file is saved as value/file inside parent zip
)
)
archive.finalize(); // line 1
);
archive.finalize(); // line 2
【问题讨论】:
看来archive.finalize()
调用得太早了。 archive.file
是异步操作吗?
好像不是。你必须向上移动archive.finalize
到fs.readdir
回调。 (我完全不明白为什么你有// line 2
)因为在添加任何文件之前调用了archive.finalize
,这似乎是在指出数据未定义的错误中
但是移动它并不会遍历所有目录,只会归档一些文件。我只有在里面(第 1 行)-> 这给了我一个 zip 文件,但不是所有文件都在里面。当我使用 readdirSync 时,它在第 2 行工作
是的,这是有道理的。一旦你在你的 foreach 循环中开始一个异步操作,archive.finalize 函数就会被调用
【参考方案1】:
我会将 fs 调用包装到 Promise 中。这使得等待操作成为可能,并且降低了代码的一些复杂性。
注意forEach
循环不适用于async, await
const children = ["path_0", "path_1", "path_2", "path_3"];
// mock fs / async action
const fs =
readdir: (path, error, success) =>
setTimeout(() =>
success(["file_0", "file_1", "file_2"]);
, Math.random() * 1000);
// function I would add to make the process simpler
const readFiles = (path) =>
return new Promise(res =>
fs.readdir(path, () => , (s) =>
res(s);
);
);
// start helper as async
const start = async() =>
// first await all files to be added to the archive
await Promise.all(children.map(async child =>
const files = await readFiles();
// loop to add all files to the zip
// archive.file(filePath, name: `$value/$file` );
console.log(child, files);
));
// then archive all files
// archive.finalize();
console.log("finalize archive");
start();
【讨论】:
以上是关于如何在遍历一系列目录的循环中使用异步 readdir 函数?的主要内容,如果未能解决你的问题,请参考以下文章