2

我知道 io-q,它是一个执行异步 IO 的库,从而产生了 Promise。但我正在寻找一个使用Q库递归遍历目录结构的简单示例,其中最终结果是所有目录中所有文件的列表,这些文件从提供给某个函数的文件夹开始,但在过程中被展平到单个文件名数组。

有这样的例子吗?或者也许有一个不是递归的例子,这很好。我猜这很简单,但这是我第一次接触异步/承诺。

4

3 回答 3

4

我发现这个要点可以满足您的需求并且很容易承诺:

var Q = require('q'),
    fs = require('fs'),
    p = require('path');
function readDir(path) {
    return Q.nfcall(fs.lstat, path).then(function(stat) {
        if (stat.isDirectory()) {
            return Q.nfcall(fs.readdir, path).then(function(files) {
                return Q.all(files
                // .map(p.join.bind(p, path)).map(readDir)
                .map(function(file) {
                    return readDir(p.join(path, file));
                })
                ).then(
                // Function.apply.bind(Array.prototype.concat, [])
                function(results) {
                    return [].concat.apply([], results);
                });
            });
        } else {
            return [path];
        }
    });
}

它用于nfcall获取文件系统 API 的承诺,并Q.all在连接它们之前等待所有子目录结果。

于 2013-10-14T14:54:07.757 回答
1

好吧,这就是我最终得出的解决方案(CoffeeScript)。我不是 Node 或 Q 专家,所以我想现在就可以了。我的解决方案实际上是扁平化列表,从输出中删除目录的方法是.then()删除read(f).

Q = require('q')
fs = require('fs')
_ = require("lodash")

isFile = (name) ->
    fs.statSync(name).isFile()

withDir = (dir) ->
    (files) -> _.map(files, (f) -> "#{dir}/#{f}")

read = (dir) ->
    Q.nfcall(fs.readdir, dir)
        .then(withDir dir)
        .then((files) -> Q.all(toPromises files))

toPromises = (files) ->
    for f in files
        if isFile f then Q(f) else read(f).then((m) -> m.concat("d " + f))

read("my-root-dir")
    .then((files) -> _.flatten(files))
    .then((r) -> console.log r)
于 2013-10-14T22:07:33.517 回答
1

Q-IO的listTree功能完全符合您的要求,因此您可以查看实现

于 2013-10-16T03:00:11.553 回答