我已经用javascript编写了一个递归承诺,它似乎运行良好,但我希望使用setTimeout()对其进行测试,以确保在继续执行之前我等待的是正确的。下面是我的代码要点:
try{
await renameFiles(); // <-- await here
console.log("do other stuff");
}
catch(){
}
const renameFiles = (path) => {
return new Promise(resolve => {
console.log("Renaming files...");
fs.readdirSync(path).forEach(file) => {
// if file is a directory ...
let newPath = path.join(path, file);
resolve( renameFiles(newPath) ); // <- recursion here!
// else rename file ...
}
resolve();
})我用这样的setTimeout()测试了它:
const renameFiles = () => {
return new Promise(resolve => {
setTimeout(() => {
// all previous code goes here
},2000)
}
}产出如下:
"Renaming files..."
"Renaming files..."
// bunch of renaming files...
"do other stuff"
"Renaming files..."
"Renaming files..."所以看起来它还在等待一段时间,但是它会在某个时候继续执行。
我也怀疑我是不是测试错了。知道问题出在哪里了吗?
发布于 2019-05-23 19:44:42
如前所述,多个解析调用没有意义。然而,这并不是代码中唯一的问题。当对第一个子目录的递归调用启动时,根调用就得到了解决。此代码将按层次顺序处理目录。
rename.js
const fs = require('fs');
const path = require('path');
const inputPath = path.resolve(process.argv[2]);
const newName = 'bar.txt';
async function renameFiles(filePath) {
for (const file of fs.readdirSync(filePath)) {
const newPath = path.join(filePath, file);
const descriptor = fs.lstatSync(newPath);
if (descriptor.isDirectory()) {
await renameFiles(newPath)
} else if (descriptor.isFile()) {
await renameFile(file);
}
}
}
async function renameFile(file) {
console.log(`Renaming ${file} to ${newName}`)
return new Promise(resolve => {
setTimeout(() => {
console.log(`Renamed ${file} to ${newName}`)
resolve();
}, 300)
});
}
async function main() {
console.log(`Renaming all files in ${inputPath} to ${newName}`);
await renameFiles(inputPath);
console.log('Finished');
}
main();你可以像
node rename.js relativeFolderName或者,如果订单不重要,那么您可以使用@Tiago中提到的map和Promise.all
const renameFiles = async path => {
const renamePromises = fs.readdirSync(path).map(file => {
if (isDirectory(file)) {
const newPath = path.join(path, file);
return renameFiles(newPath)
} else {
return renamefile(file);
}
});
await Promise.all(renamePromises);
}发布于 2019-05-23 19:41:36
要使此工作正常,您需要等待目录中的所有文件进行解析。因此,您需要执行一个Promise.all,使用map而不是forEach。
就像这样:
try{
await renameFiles(); // <-- await here
console.log("do other stuff");
}
catch(){
}
const renameFiles = (path) => {
return new Promise(resolve => {
console.log("Renaming files...");
const allFilesRenamePromises = fs.readdirSync(path).map(file => {
if(file.isDirectory()) {
let newPath = path.join(path, file);
return renameFiles(newPath); // <- recursion here!
} else {
// rename file ...
}
}
resolve(Promise.all(allFilesRenamePromises));
})发布于 2019-05-25 03:55:23
我建议采用一种更分解的方法,而不是编写一个大的复杂函数。
首先,我们从一个files开始,它递归地列出指定path中的所有文件-
const { readdir, stat } =
require ("fs") .promises
const { join } =
require ("path")
const files = async (path = ".") =>
(await stat (path)) .isDirectory ()
? Promise
.all
( (await readdir (path))
.map (f => files (join (path, f)))
)
.then
( results =>
[] .concat (...results)
)
: [ path ]我们现在有一种方法来列出所有的文件,但是我们只想重命名其中的一些文件。我们将编写一个通用的search函数来查找与查询匹配的所有文件-
const { basename } =
require ("path")
const search = async (query, path = ".") =>
(await files (path))
.filter (x => basename (x) === query)现在我们可以把你的renameFiles函数写成search的专门性-
const { rename } =
require ("fs") .promises
const { dirname } =
require ("path")
const renameFiles = async (from = "", to = "", path = ".") =>
Promise
.all
( (await search (from, path))
.map
( f =>
rename
( f
, join (dirname (f), to)
)
)
)要使用它,我们只需使用它的预期参数来调用renameFiles -
renameFiles ("foo", "bar", "path/to/someFolder")
.then
( res => console .log ("%d files renamed", res.length)
, console.error
)
// 6 files renamed回顾上面的程序,我们看到随着Promise.all、await和map的使用,出现了一些模式。事实上,这些模式可以被提取,我们的程序可以进一步简化。下面是files和renameFiles修改后使用的通用Parallel模块-
const files = async (path = ".") =>
(await stat (path)) .isDirectory ()
? Parallel (readdir (path))
.flatMap (f => files (join (path, f)))
: [ path ]
const renameFiles = (from = "", to = "", path = "") =>
Parallel (search (from, path))
.map
( f =>
rename
( f
, join (dirname (f), to)
)
)Parallel模块最初是在this related Q&A中派生的。要获得更多的洞察力和解释,请点击链接。
https://stackoverflow.com/questions/56281473
复制相似问题