gpt4 book ai didi

javascript - 如何并行遍历目录树?

转载 作者:行者123 更新时间:2023-12-02 20:51:40 25 4
gpt4 key购买 nike

首先我想描述一下问题:我有一个目录树(深度= 3),其中包含多个目录和文件。其中一些文件的扩展名为 .txt,一些文件的扩展名为 .mp4。我只想复制新目录中的 .mp4 文件,其层次结构与源目录中的相同(换句话说,我不想复制一个文件夹中的所有 mp4 文件,我想按原样复制所有目录,然后复制 mp4 文件)。问题是:如何不串行而是并行地复制这些文件?这是我的代码:

const fs = require('fs');
const path = require('path');
const { promisify } = require('util');

const sourceDir = process.argv[2];
const stat = promisify(fs.stat);
const copy = promisify(fs.copyFile);
const mkdir = promisify(fs.mkdir);
const readdir = promisify(fs.readdir);
const targetDir = path.join(__dirname, 'only-mp4');

// creating root folder, all files will be copied here
(async () => {
await mkdir(targetDir);
})();

const copyMediaFiles = async (node) => {
try {
const stats = await stat(node);
if (stats.isDirectory()) {
let children = await readdir(node);
// constructing new paths
children = children.map((child) => path.join(node, child));
// "copying" file hierarchy (basically just recreating same file hierarchy in target directory)
children.forEach((child) => {
const courseDirs = child.split('/').slice(4, 7).join('/');
mkdir(path.join(targetDir, courseDirs), { recursive: true });
});
// running this function for all children recursively in parallel
const promises = children.map(copyMediaFiles);
await Promise.all(promises);
}
const ext = path.extname(node);
const filename = path.basename(node);
// if file extension == mp4 then copy that file in target directory
if (ext === '.mp4') {
await copy(
node,
path.join(
targetDir,
path.dirname(node).split('/').slice(4).join('/'),
filename
)
);
console.log('File copied: ', filename);
}
return;
} catch (error) {
console.log(error);
}
};

copyMediaFiles(sourceDir).then(() => console.log('All mp4 files copied'));

是的,它正在工作,但我不确定我是否做对了。有什么建议吗?我在这里做错了什么?而且我不确定我是否正确地遍历了这棵树。

最佳答案

两个问题:

  • 第一次调用 copyMediaFiles 将在第一个 mkdir Promise 解析之前发生。这是有风险的,因为您实际上可能会在目标目录创建完成之前尝试访问它。如果您只是将 copyMediaFiles 的调用放在 async IIFE 中,那么您就不会遇到这种风险:

    (async () => {
    await mkdir(targetDir);
    await copyMediaFiles(sourceDir);
    console.log('All mp4 files copied');
    })();
  • 第二次调用 mkdir 时没有捕获它返回的 Promise,因此也会出现类似的风险。

进一步“压缩”的可能改进:

您的目标是最大限度地减少 JavaScript 空闲时间(等待 promise 解决),并且可以通过最大化待处理的 promise 数量来实现这一目标。

因此,最好在相应的 mkdir promise 解析后立即启动对 copyMediaFiles 的调用,而不是在之前先启动所有同级目录的创建调用电话:

const children = await readdir(node);
const promises = children.map(async child => {
child = path.join(node, child);
const courseDirs = child.split('/').slice(4, 7).join('/');
await mkdir(path.join(targetDir, courseDirs), { recursive: true });
await copyMediaFiles(child);
});
await Promise.all(promises);

使用此代码,您可能会在创建所有同级目录之前启动 copyMediaFiles 调用。如果您的目录具有较高的分支因子,那么这意味着您将获得更长的待处理 promise 列表,这可能有利于整体性能。

一切都取决于底层 API 管理并发的能力。

关于javascript - 如何并行遍历目录树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61595999/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com