如何(不)嵌套 `then` 产生 promise 方法?

How (not) to nest `then` producing promise methods?

使用 bluepird promisified fs 方法的干净方法是什么? readdir 将生成一个文件和文件夹数组,但如果我依次循环遍历它提供的目录,我最终会编写一些非常类似于回调嵌套范例的东西(除了它甚至不起作用)。以这样一种方式链接这些承诺的标准做法是什么,使得它们的 return 值可以循环通过?

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs-extra'));
var path = require('path');
var junk = require('junk');

//this does not work
fs.readdirAsync('./node_modules')
  .bind(this)
  .then((modules) => {
    this.allFiles = [];
    modules = modules.filter((item) => junk.not && !/^\./.test(item)); 
    modules.forEach((module, index, modulesArray) => {
      fs.readdirAsync(path.join('node_modules', module)) //ugly af and don't even get files to next `then`!
        .then((files) => { 
          console.log(files); // yep, array of files all right
          this.allFiles.push(files);
        });
    })
  })
  .then(() => {
    console.log('all of the files', this.allFiles) // => [] no files 
  })
  .catch((err) => {
    console.error('error! error!', err);
  })

您没有在第一个外部 then 中返回承诺。因此,您的外部承诺链不会等待文件被读取。

您可以使用 Promise.all + map 来做到这一点。我的第二个建议是不要使用 this 来存储您的值,而是通过您的承诺链传递所有需要的信息。这使得代码更短:

fs.readdirAsync('./node_modules')
  .then((modules) => {
    return Promise.all(modules.filter((item) => junk.not && !/^\./.test(item))
      .map(module => fs.readdirAsync(path.join('node_modules', module))));
  })
  .then(allFiles => {
    console.log('all of the files', allFiles);
  })
  .catch((err) => {
    console.error('error! error!', err);
  });