使用承诺和递归迭代文件目录
Iterating file directory with promises and recursion
我知道我将在以下函数中提前返回,如何将递归承诺链接到我的结果?
我的目标是获取目录中的文件列表数组及其所有子目录。数组是单维的,我在这个例子中使用了 concat。
function iterate(body) {
return new Promise(function(resolve, reject){
var list = [];
fs.readdir(body.path, function(error, list){
list.forEach(function(file){
file = path.resolve(body.path, file);
fs.stat(file, function(error, stat){
console.log(file, stat.isDirectory());
if(stat.isDirectory()) {
return iterate({path: file})
.then(function(result){
list.concat(result);
})
.catch(reject);
} else {
list.push(file);
}
})
});
resolve(list);
});
});
};
您的代码中有许多错误。 部分列表:
-
.concat()
返回一个新数组,因此list.concat(result)
本身实际上不会执行任何操作。 -
您正在同步调用
resolve()
,而不是等待所有异步操作完成。 -
您正在尝试从几个嵌套异步回调的深处递归返回。 你不能这么做。 这不会在任何地方获得结果。
我发现通过使用 fs
模块的 prodid 版本,这更容易使用。 我使用蓝鸟来创建它,然后你可以这样做:
const path = require('path');
var Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
function iterate(dir) {
return fs.readdirAsync(dir).map(function(file) {
file = path.resolve(dir, file);
return fs.statAsync(file).then(function(stat) {
if (stat.isDirectory()) {
return iterate(file);
} else {
return file;
}
})
}).then(function(results) {
// flatten the array of arrays
return Array.prototype.concat.apply([], results);
});
}
注意:我更改了iterate()
,只采用初始路径,因此它更通用。 您可以先将body.path
传递给它以适应。
以下是使用通用 ES6 承诺的版本:
const path = require('path');
const fs = require('fs');
fs.readdirAsync = function(dir) {
return new Promise(function(resolve, reject) {
fs.readdir(dir, function(err, list) {
if (err) {
reject(err);
} else {
resolve(list);
}
});
});
}
fs.statAsync = function(file) {
return new Promise(function(resolve, reject) {
fs.stat(file, function(err, stat) {
if (err) {
reject(err);
} else {
resolve(stat);
}
});
});
}
function iterate2(dir) {
return fs.readdirAsync(dir).then(function(list) {
return Promise.all(list.map(function(file) {
file = path.resolve(dir, file);
return fs.statAsync(file).then(function(stat) {
if (stat.isDirectory()) {
return iterate2(file);
} else {
return file;
}
});
}));
}).then(function(results) {
// flatten the array of arrays
return Array.prototype.concat.apply([], results);
});
}
iterate2(".").then(function(results) {
console.log(results);
});
这是一个添加可自定义过滤器功能的版本:
function iterate2(dir, filterFn) {
// default filter function accepts all files
filterFn = filterFn || function() {return true;}
return fs.readdirAsync(dir).then(function(list) {
return Promise.all(list.map(function(file) {
file = path.resolve(dir, file);
return fs.statAsync(file).then(function(stat) {
if (stat.isDirectory()) {
return iterate2(file, filterFn);
} else {
return filterFn(file)? file : "";
}
});
})).then(function(results) {
return results.filter(function(f) {
return !!f;
});
});
}).then(function(results) {
// flatten the array of arrays
return Array.prototype.concat.apply([], results);
});
}
// example usage
iterate2(".", function(f) {
// filter out
return !(/(^|'/)'.[^'/'.]/g).test(f);
}).then(function(results) {
console.log(results);
});
相关文章:
- 迭代 JSON 文件并且未在 Javascript 中正确返回结果
- 文件夹迭代器中的Google驱动器文件迭代器
- PHP对目录文件进行迭代
- 只有最后一个文件是通过迭代形式.submit()操作下载的
- 如何使用 D3 javascript 迭代 JSON 文件中的数据
- 使用 promises/dedelay 异步迭代一组文件
- 如何递归迭代要使用 Promise 获取的文件树结构
- 服务器端迭代目录中的文件
- 谷歌应用脚本 - 迭代文件夹和子文件夹
- Node.js将大文件拆分为多个部分,并对这些部分进行迭代
- 如何迭代Google Analytics配置文件ID's
- 使用XPath使用JavaScript在XML文件中的子节点上进行迭代
- 获取按钮,显示XML文件中循环的下一次迭代
- 快速迭代时处理缓存js文件的最佳方式
- 在web工作者javascript文件中迭代100000个索引的数组会冻结浏览器
- 使用纯javascript和ajax迭代json文件
- 如何在外部jquery.js文件中获取PHP迭代变量
- Google Apps 脚本中的文件迭代器在搜索不存在的文件时返回无效参数
- 使用承诺和递归迭代文件目录
- Ember.js / Ember-i18n:是否可以从 Handlebars 模板中迭代翻译文件中的属性