javascript - Promises.all() 在具有 'promised' 属性的对象数组上

标签 javascript node.js promise bluebird

编辑:在提出这个问题后的短短几个小时内,我学到了足够多的知识,意识到这个问题是对严重滥用 promise 的完美案例研究:

我正在尝试将工作流转换为使用 promises,因为它是一个可怕的回调巢穴,而且我进展顺利,直到我得到一个特定的函数。我正在尝试使用 readFile() 的 promisified 版本来获取一系列文件的内容,但我还需要保留每个文件的文件名,以便将其添加到最终将被解析的对象中下一步/功能中的文件内容。只有在我遍历文件名列表(并创建返回文件内容的 promise )时才能访问此文件名。现在我有这个,这是行不通的:

    // Accepts a sequence of filenames and returns a sequence of objects containing article contents and their filenames
    function getAllFiles(filenames) {
      var files = []; // This will be an array of objects containing Promises on which we want to call .all()
      filenames.each( function (filename) {
        files.push({content: fsPromise.readFileAsync(articlesPath + '/' + filename, 'utf8'), 
                   filename: filename});    
      });

这是试图表达我下一步想做什么:

      Promise.all(files).then( function(files) {
        return Lazy(files);
      });
    } 

换句话说,我想从 promises 数组中得到的是一个对象数组,如 {content: "FILE CONTENTS", filename: "fileN.txt"}。第一部分是 readFileAsync() 的结果,因此这是一个在我可以继续下一步之前需要解决的 promise 。据我所知,filenames.each() 调用是我将文件内容与其来源文件的名称相关联的唯一机会。我无法控制文件的内容,所以我无法将文件名存储在文件内容中,这将是丑陋的数据冗余,而且无论如何都是一个坏主意。 Lazy() 调用只是将完成的数组转换为 lazy.js 序列,因为这是我在项目其余部分中用于集合处理的库。

我正在考虑的半解决方案

是否可以从对象中提取 promise 部分并将它们存储在单独的数组中,然后对其调用 .all()?换句话说,当所有的 promise 都完成后,我回到原来的数组并通过索引检索匹配的文件名?如果我能够使用对原始 promise 的引用填充第二个数组,我觉得这会起作用(也就是说,我知道原始 promise 何时解决)。这行得通吗?

或者,

我可以在 .each() 调用中进行同步吗?例如。

filenames.each( function(filename) {
  files.push({content: fsPromise.readFileAsync(articlesPath + '/' + filename, 'utf8')
              .then( function(fulfilledContent) {return fulfilledContent}), 
              filename: filename
});

(我知道我还需要处理这些 promise 被拒绝而不是解决的可能性——一旦我想出我想做的事情是否可行,我会想办法做到这一点)

最佳答案

有两个简单的解决方案:

  • 在上一个回调中访问filenames 数组。它与 Promise.all 将实现的内容数组的顺序相同:

    Promise.all(filenames.map(function(filename) {
        return fsPromise.readFileAsync(articlesPath + '/' + filename, 'utf8');
    })).then(function(contents) {
        return Lazy(contents).map(function(content, i) {
            return {content: content, filename: filenames[i]};
        });
    })
    
  • 在遍历数组时,立即为包含文件名和内容的对象做出 promise :

    Promise.all(filenames.map(function(filename) {
        return fsPromise.readFileAsync(articlesPath + '/' + filename, 'utf8').then(function(content) {
            return {content: content, filename: filename};
        });
    })).then(Lazy);
    

关于javascript - Promises.all() 在具有 'promised' 属性的对象数组上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35460764/

相关文章:

javascript - 检查进程 A 写入的文件是否准备好被进程 B 读取

javascript - 暂停视频后触发点击文件上传

mysql - 类型错误 : Converting circular structure to JSON when getting data from mysql DB

javascript - 无法将 elementIsNotVisible 与 selenium webdriver 用于 javascript

javascript - zClip 不起作用 - 多次复制到剪贴板 JS

javascript - Jquery 将最后的输出作为值

node.js - gulp-util 现在包含在 gulp 的 npm 安装中了吗?

javascript - 从 url 获取路由参数

javascript - 无法解析对象中的 promise

javascript - 为什么这个 JavaScript Promise reject() 在结果回调中得到处理?