web-dev-qa-db-fra.com

chaîner `fs.readdir` avec un` .then` pour retourner un tableau

J'essaie de créer un tableau de fichiers spécifiques dans un répertoire; qui passera par quelques cas de test pour s'assurer qu'il correspond à un critère donné.

J'utilise la méthode fs.readdir, Mais elle ne renvoie pas un promise ce qui signifie que je ne peux pas Push vers un array.

Mon idée était de remplir un tableau (arr) avec les fichiers que je veux réellement sortir, puis de faire quelque chose avec ce tableau. Mais parce que readdir est asynchrone et que je ne peux pas y chaîner une .then(), mes plans sont annulés.

J'ai également essayé la même chose avec readdirSync en vain.

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);
});
8
grpcMe

Je l'ai compris; Je devais juste utiliser statSync au lieu de 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
grpcMe

fs.readdir est basé sur le rappel, vous pouvez donc le promisify en utilisant bluebird (ou en écrire vous-même une simple implémentation), ou simplement envelopper l'appel dans une promesse, comme ceci:

// Wrapped in a promise
new Promise((resolve, reject) => {
    return fs.readdir('/folderpath', (err, filenames) => err !== undefined ? reject(err) : resolve(filenames))
})

Ou la fonction personnalisée 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))
9

Juste du javascript, pas de bibliothèques:

function foo (folder, enconding) {
    return new Promise(function(resolve, reject) {
        fs.readdir(folder,enconding, function(err, filenames){
            if (err) 
                reject(err); 
            else 
                resolve(filenames);
        });
    });
};

par exemple

foo(someFolder, "someEncoding")
.then((files) => console.log(files))
.catch((error) => console.log(error));
5
Marcus Fonseca

si vous souhaitez utiliser une promesse au lieu d'un rappel, vous pouvez promettre fs.

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));

fs.readdirAsync('./some').then()

http://bluebirdjs.com/docs/api/promise.promisifyall.html

2
Karim

Avez-vous essayé le module fs-extra ?

1
Kristian
new Promise((resolve, reject) => {
    return fs.readdir('/folderpath', (err, filenames) => err ? reject(err) : resolve(filenames))
})

Ne pas err !== undefined parce que l'erreur est en fait null !!

0
pautasso