将 `fs.readdir` 与 `.then` 链接以返回一个数组
Posted
技术标签:
【中文标题】将 `fs.readdir` 与 `.then` 链接以返回一个数组【英文标题】:chaining `fs.readdir` with a `.then` to return an array 【发布时间】:2017-10-16 14:08:39 【问题描述】:我正在尝试在目录中创建一组特定文件;这将通过一些测试用例来确保它符合给定的标准。
我正在使用fs.readdir
方法,但它没有返回promise
,这意味着我不能将push
传递给array
。
我的想法是用我实际想要输出的文件填充一个数组 (arr
),然后对该数组执行一些操作。但是因为readdir
是异步的,我不能将.then()
链接到它上面,所以我的计划被取消了。
我也用readdirSync
尝试过同样的事情,但无济于事。
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
var arr = [];
fs.readdirAsync(folder).then( files =>
files.forEach(file =>
fs.stat(folder + '/' + file, (err, stats) =>
if(!stats.isDirectory())
arr.push(file);
return;
);
);
)
.then( () =>
console.log(arr);
);
【问题讨论】:
为什么不能使用回调? --- 您可以编辑您的问题以包含您的努力的minimal reproducible example 吗? “我也用 readdirSync 尝试过同样的事情,但无济于事”。该函数将返回一个文件名数组,在我看来这正是你要找的? 添加了一个我正在尝试做的例子。arr
返回[]
【参考方案1】:
你试过fs-extra模块吗?
【讨论】:
【参考方案2】:如果您想使用承诺而不是回调,您可以承诺 fs
。
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.readdirAsync('./some').then()
http://bluebirdjs.com/docs/api/promise.promisifyall.html
【讨论】:
刚刚添加了一个我正在尝试做的示例 - 在最后一个.then()
arr
返回为 []
【参考方案3】:
fs.readdir
是基于回调的,因此您可以使用 bluebird 或 Node.js util
包 promisify
它(或自己编写一个简单的实现),或者简单地将调用包装在一个承诺中,就像这样:
// Wrapped in a promise
new Promise((resolve, reject) =>
return fs.readdir('/folderpath', (err, filenames) => err != null ? reject(err) : resolve(filenames))
)
或者自定义promisify
函数:
// Custom promisify
function promisify(fn)
/**
* @param ...Any params The params to pass into *fn*
* @return Promise<Any|Any[]>
*/
return function promisified(...params)
return new Promise((resolve, reject) => fn(...params.concat([(err, ...args) => err ? reject(err) : resolve( args.length < 2 ? args[0] : args )])))
const readdirAsync = promisify(fs.readdir)
readdirAsync('./folderpath').then(filenames => console.log(filenames))
【讨论】:
我已经尝试添加一个承诺,但arr
数组仍然返回[]
。我添加了一个示例,希望能澄清我在做什么。这是第一次使用readddir
,所以完全有可能我用错了。
我不得不做 err !== null,但这就像一个魅力,谢谢!
err ? reject(err) : resolve(filenames)
=> 自从 err 为我返回 null 后,第一个代码开始运行!
哦,开枪,不知道为什么我这样做了!== undefined
,默认行为是返回null
...更新了我的答案【参考方案4】:
我想通了;我只需要使用statSync
而不是stat
const fs = require('fs');
var arr = [];
var files = fs.readdirSync(folder);
files.forEach(file =>
let fileStat = fs.statSync(folder + '/' + file).isDirectory();
if(!fileStat)
arr.push(file);
);
console.log(arr);
【讨论】:
正是我所追求的。谢谢。【参考方案5】:只是普通的 javascript,没有库:
function foo (folder, enconding)
return new Promise(function(resolve, reject)
fs.readdir(folder,enconding, function(err, filenames)
if (err)
reject(err);
else
resolve(filenames);
);
);
;
例如
foo(someFolder, "someEncoding")
.then((files) => console.log(files))
.catch((error) => console.log(error));
【讨论】:
【参考方案6】:new Promise((resolve, reject) =>
return fs.readdir('/folderpath', (err, filenames) => err ? reject(err) : resolve(filenames))
)
不要err !== undefined
,因为err实际上是null
!!
【讨论】:
您实际上可以进一步简化它。由于您只有一个语句并且您使用的是箭头函数,因此您可以删除大括号和“return”,它会正常工作。【参考方案7】:从 Node.js v10 开始,有一个支持此功能的 fs.promises
API:
const fs = require('fs');
var arr = [];
fs.promises.readdir(folder).then( files =>
files.forEach(file =>
fs.stat(folder + '/' + file, (err, stats) =>
if(!stats.isDirectory())
arr.push(file);
return;
);
);
)
.then( () =>
console.log(arr);
);
【讨论】:
【参考方案8】:您现在可以使用 ES6 解构赋值 (documentation):
const
fs = require('fs'),
FILES = [...fs.readdirSync('src/myfolder')];
console.log(FILES);
【讨论】:
真漂亮以上是关于将 `fs.readdir` 与 `.then` 链接以返回一个数组的主要内容,如果未能解决你的问题,请参考以下文章
无法从 fs.readdir 获取 fs.Dirent 数组