【问题标题】:chaining `fs.readdir` with a `.then` to return an array将 `fs.readdir` 与 `.then` 链接以返回一个数组
【发布时间】: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 返回[]

标签: javascript node.js fs


【解决方案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 utilpromisify 它(或自己编写一个简单的实现),或者简单地将调用包装在一个承诺中,就像这样:

    // 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);
        

        【讨论】:

        • 真漂亮
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-03
        相关资源
        最近更新 更多