使用蓝鸟递归迭代目录
Iterate directories recursively with bluebird
我正在尝试使用 Node 和 Bluebird(promises 库)递归地迭代给定目录,但就目前而言它似乎无法正常工作。
当我取消注释下面的 'console.log' 行时,似乎 我得到了正确的结果,但我不确定发生了什么,因为最终结果我从下面的使用代码中得到的只是第一个目录中的第一个文件。
也许问题不在于迭代函数本身,而在于我使用它的方式。
我对 promises 有点陌生,所以也许我只是以错误的方式接近它。
这是我写的代码。
import * as Path from "path";
import * as Promise from "bluebird";
const FS: any = Promise.promisifyAll<any>((require("fs")));
export class Dir {
public static iterate(path: string) {
return new Promise((resolve, reject) => {
FS.lstatAsync(path).then(stat => {
if (stat.isDirectory()) {
FS.readdirAsync(path).each(name => {
let fullPath = Path.join(path, name);
// console.log(fullPath);
FS.lstatAsync(fullPath).then(stat => stat.isDirectory() ? Dir.iterate(fullPath) : resolve(fullPath));
});
} else {
reject(`The path '${path}' is not a directory.`)
}
});
})
}
}
我是这样的using/consuming
Dir.iterate(ProjectPaths.client)
.then(f => {
console.log(f)
return f;
})
.catch(e => console.log(e));
编辑: 澄清一下我使用的是 TypeScript!忘了在我的 post.
中提到它
基于 Petka 在 bluebird API 文档中的代码,这里是一个使用 bluebird 递归迭代目录的注释示例:
function readDir(dirName) { // reading a directory requires its name
return fs.readdirAsync(dirName).map(fileName => { // for each file we take it
var path = Path.join(dirName, fileName); // get the correct path
// if it's a directory we scan it too recursively, otherwise we just add it
return fs.statAsync(path).then(stat => stat.isDirectory() ? readDir(path) : path);
}).reduce((a, b) => a.concat(b), []); // we flatten the result to an array
}
或更多"clever" ES2015风格:
const readDir => dirName => fs.readdirAsync(dirName).map(fileName => {
var path = Path.join(dirName, fileName);
return fs.statAsync(path).then(stat => stat.isDirectory() ? readDir(path) : path);
}).reduce((a, b) => a.concat(b), []);
不需要 explicit construction 作为承诺链。您的尝试失败了,因为您正在解决每个内部文件的外部承诺,承诺只解决一次。
我正在尝试使用 Node 和 Bluebird(promises 库)递归地迭代给定目录,但就目前而言它似乎无法正常工作。
当我取消注释下面的 'console.log' 行时,似乎 我得到了正确的结果,但我不确定发生了什么,因为最终结果我从下面的使用代码中得到的只是第一个目录中的第一个文件。
也许问题不在于迭代函数本身,而在于我使用它的方式。
我对 promises 有点陌生,所以也许我只是以错误的方式接近它。
这是我写的代码。
import * as Path from "path";
import * as Promise from "bluebird";
const FS: any = Promise.promisifyAll<any>((require("fs")));
export class Dir {
public static iterate(path: string) {
return new Promise((resolve, reject) => {
FS.lstatAsync(path).then(stat => {
if (stat.isDirectory()) {
FS.readdirAsync(path).each(name => {
let fullPath = Path.join(path, name);
// console.log(fullPath);
FS.lstatAsync(fullPath).then(stat => stat.isDirectory() ? Dir.iterate(fullPath) : resolve(fullPath));
});
} else {
reject(`The path '${path}' is not a directory.`)
}
});
})
}
}
我是这样的using/consuming
Dir.iterate(ProjectPaths.client)
.then(f => {
console.log(f)
return f;
})
.catch(e => console.log(e));
编辑: 澄清一下我使用的是 TypeScript!忘了在我的 post.
中提到它基于 Petka 在 bluebird API 文档中的代码,这里是一个使用 bluebird 递归迭代目录的注释示例:
function readDir(dirName) { // reading a directory requires its name
return fs.readdirAsync(dirName).map(fileName => { // for each file we take it
var path = Path.join(dirName, fileName); // get the correct path
// if it's a directory we scan it too recursively, otherwise we just add it
return fs.statAsync(path).then(stat => stat.isDirectory() ? readDir(path) : path);
}).reduce((a, b) => a.concat(b), []); // we flatten the result to an array
}
或更多"clever" ES2015风格:
const readDir => dirName => fs.readdirAsync(dirName).map(fileName => {
var path = Path.join(dirName, fileName);
return fs.statAsync(path).then(stat => stat.isDirectory() ? readDir(path) : path);
}).reduce((a, b) => a.concat(b), []);
不需要 explicit construction 作为承诺链。您的尝试失败了,因为您正在解决每个内部文件的外部承诺,承诺只解决一次。