【问题标题】:Combine result of promises into a single array in JavaScript在 JavaScript 中将 Promise 的结果合并到一个数组中
【发布时间】:2018-12-09 19:33:57
【问题描述】:

我尝试将作为目录上传的所有文件解析为单个文件数组。我有一个问题,我无法将所有承诺的结果合并到一个数组中。我得到了一个多维数组。

function iterateThroughUploadedFiles(files, isEntry = false) {
    var promises = [];
    for (let i = 0; i < files.length; i++) {
        let entry = isEntry ? files[i].webkitGetAsEntry() : files[i];
        if (entry.isFile) {
            promises.push(new Promise(function(resolve, reject) {
                getFile(entry, resolve, reject);
            }));
        }
        else if (entry.isDirectory) {
            let dirReader = entry.createReader();

            var promise = new Promise(function(resolve, reject) {
                readEntries(dirReader, resolve, reject);
            });

            promises = promises.concat(promise);
        }
    }
    return Promise.all(promises);
}

function getFile(fileEntry, resolve, reject) {
    fileEntry.file(function(file) {
        resolve(file)
    });
}

function readEntries(dirReader, resolve, reject) {
    dirReader.readEntries(function (entries) {
        resolve(iterateThroughEntries(entries).then(function(result) {
            return result;
        }));
    });
}

用法:

iterateThroughUploadedFiles(files, true).then(function(result) {
    console.log(result);
});

当我执行iterateThroughUploadedFiles 函数时,result 变量是一个多维数组。但是,我希望这个数组被展平(例如:[File(6148), Array(1), Array(0), File(14)])。我对回调和承诺不是很熟悉......因此,我在使用它们时遇到了一些问题。

编辑:
我在readEntries(dirReader, resolve, reject) 函数中犯了一个错字。应该有iterateThroughUploadedFiles而不是iterateThroughEntries函数。

【问题讨论】:

  • readEntriesgetFile 应该返回一个他们自己构建的承诺,而不是把 resolve/reject 作为回调。

标签: javascript arrays callback promise es6-promise


【解决方案1】:
return Promise.all(promises);

这解析为一个二维数组,您可以使用一些生成器函数轻松地将其展平:

function* flatten(arr) {
  for(const el of arr) {
    if(Array.isArray(el)) {
      yield* flatten(el);
    } else {
      yield el;
    }
  }
}

return Promise.all(promises).then(array => ([...flatten(array)]));

虽然传递 resolvereject 有点作用,但只需从 getFile 函数返回一个新的 Promise 就可以做得更优雅:

function getFile(fileEntry, resolve, reject) {
   return new Promise(resolve => fileEntry.file(resolve));
}

那么就可以轻松上链了

function readEntries(dirReader) {
  return new Promise(resolve => dirReader.readEntries(resolve))
    .then(iterateThroughEntries);
}

function iterateThroughUploadedFiles(files, isEntry = false) {
   return Promise.all( files.map( file => {
     let entry = isEntry ? file.webkitGetAsEntry() : file;
     if (entry.isFile) {
       return getFile(entry);
     } else if (entry.isDirectory) {
       return readEntries( entry.createReader());
     }
   })).then(array => ([...flatten(array)]));
}

【讨论】:

  • 我会认为array =&gt; [].concat(...array) 将是如何展平二维数组 - 如果有问题的 JS 引擎支持箭头函数但不支持扩展运算符,甚至是 [].concat.apply([], array)
  • 这只能解决二维问题,但我是否有可能拥有更多维数组。
  • @david,是的,看看编辑后的版本;)
猜你喜欢
  • 1970-01-01
  • 2017-11-18
  • 1970-01-01
  • 2021-10-11
  • 2017-10-14
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多