chaining `fs.readdir` with a `.then` to return an array

a 夏天 提交于 2019-11-27 18:55:16

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!