问题
I am trying to create an array of specific files in a directory; which will go through a few test cases to make sure it fits a given criteria.
I'm using the fs.readdir
method, but it doesn't return a promise
meaning I cannot push
to an array
.
My idea was to populate an array (arr
) with the files I actually want to output and then do something with that array. But because readdir
is asynchronous and I can't chain a .then()
onto it, my plans are quashed.
I've also tried the same thing with readdirSync
to no avail.
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);
});
回答1:
fs.readdir
is callback based, so you can either promisify
it using bluebird (or writing a simple implementation of it yourself), or simply wrap the call in a promise, like so:
// Wrapped in a promise
new Promise((resolve, reject) => {
return fs.readdir('/folderpath', (err, filenames) => err !== undefined ? reject(err) : resolve(filenames))
})
Or the custom promisify
function:
// 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))
回答2:
Just plain javascript, no libs:
function foo (folder, enconding) {
return new Promise(function(resolve, reject) {
fs.readdir(folder,enconding, function(err, filenames){
if (err)
reject(err);
else
resolve(filenames);
});
});
};
e.g
foo(someFolder, "someEncoding")
.then((files) => console.log(files))
.catch((error) => console.log(error));
回答3:
I figured it out; I just needed to use statSync
instead of 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);
回答4:
if you want to use a promise instead of a callback you can promisify fs
.
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.readdirAsync('./some').then()
http://bluebirdjs.com/docs/api/promise.promisifyall.html
回答5:
Have you tried fs-extra module?
来源:https://stackoverflow.com/questions/44019316/chaining-fs-readdir-with-a-then-to-return-an-array