这个 Promise.all() 语句在我的代码中究竟是如何工作的?

How exactly works this Promise.all() statement in my code?

我在 JavaScript 技术和 RxJS 方面还很陌生,我对这段代码的工作原理有以下疑问。它取自我正在工作的一个项目,它工作正常,但我需要了解 Promise.all() 究竟如何工作以及如何在此代码中使用它。

所以基本上我使用这种方法在 Firebase 商店中保存多个文件:

public async saveAsset(parameters: any, filesList: any[]) {
    console.log("saveAsset() START, parameters: ", parameters);

    if(filesList != null) {
      //return await this.uploadFileIntoFirebaseStore(filesList);

      let files: any[] = [];
      if (filesList) {                            // If exist files that have to be updated

        /**
         * Retrieve files URLs list on Firebase Storage.
         * uploadFileIntoFirebaseStore() receive the files list to be uploaded and return a Promise resolving 
         * an array of string representing the URLs where of the uploaded files.
         * 
         */
        files = (await Promise.all(this.uploadFileIntoFirebaseStore(filesList)))
          .map(url => {
            console.log("UPLOADED URL: ", url);
            return {
              url
            };
          });
      }

    }
    else {
      //return await this.firestore.collection('assets').doc().set(parameters);
    }

}

基本上我的 saveAsset() 方法接收 filesList 参数,该参数是用户上传的必须保存的文件列表在 Firebase 存储上。保存文件后,我必须存储文件 URL.

为了保存这些文件,使用了 uploadFileIntoFirebaseStore() 方法 returning a Promise[]。所以它是 return 一个包含 n 个 Promise 对象的数组。

所以如果我很好地理解 Promise 概念(如果我做错了断言请纠正我)我的 uploadFileIntoFirebaseStore() 方法是 returning 一个 Promise 类型的对象,它基本上可以做两件不同的事情:

  1. 它可以解析为字符串数组(其中每个字符串代表 Firebase 存储中上传文件的 URL)。
  2. 万一发生错误被拒绝(我认为如果文件上传失败可能会发生)。

所以根据我对 Promise.all() 方法的使用的了解,它会在我的数组的所有承诺都得到解决之后做一些事情。所以在我的代码中我有:

await Promise.all(this.uploadFileIntoFirebaseStore(filesList))

如果我很好地理解这个概念,这意味着我的 uploadFileIntoFirebaseStore 执行我在 Firebase 存储中的文件的有效上传和 return Promise 数组,其中每个 promises 可以在上传中解决URL。此行为是异步的,因为一个文件可以在其他文件之后或之前上传。这里是第一个疑问:我的 Promise 数组立即被 returned,然后开始以异步方式解决 promise,或者当相关文件开始上传时发出 Promise 对象(类似于 Observable) .我认为行为是第一个,但我不确定。

第二个疑问与Promise.all()方法前面的await关键字有关。也就是说这是一个async方法?据我所知,await 关键字只能与异步方法一起使用。

最后一个疑惑是:看了各种教程和文档,发现经常是这样的:

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});

基本上我有 n 个 Promise 对象作为数组传递给 Promise.all() 方法作为数组然后我有 then() 方法执行箭头当数组的所有 promises 对象都被解析时函数(我也可以让 catch() 方法在被拒绝的情况下做一些事情)。

这与我的代码完全不同,在我的代码中,我没有 then() 方法在我的所有承诺都已解决时执行某些操作。相反,我的代码在(已解决的?)承诺列表中使用 RxJS map() 运算符。

据我所知,此 map() 运算符迭代 returned 已解决的承诺,其中包含相关文件的 url,以便在控制台中打印它并且 return 它作为 Observable(在我看来 map() 总是 return 一个 Observable,对吗?)

这个语法究竟是如何工作的?为什么不使用 then()?

Promise.all

它将接受一组承诺并并行执行它们。 它遵循 all 或 none

的机制

Promise.all([ ...]).then(console.log) 将在所有承诺 fulfilled,否则会执行catch Promise.all([ ...]).catch(console.log)

还有一个方法Promise.all解决了 即使其中一个承诺失败,这也将视为成功。 return 数据包含所有带有雕像的结果

语法:-

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];

Promise.all(promises)
  .then((results) => results.forEach((result) => console.log(result)))
  .catch(console.error);

这是一个很大的问题,如果我没有回答所有方面,请见谅。仔细看括号的个数:

files = (await Promise.all(this.uploadFileIntoFirebaseStore(filesList)))

此处,await 的语法(参见:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)将 等待 传递给 Promise.all 的 Promise。

这意味着,上面的括号将最终计算为数组(不是承诺)。

有了字符串数组,可以调用map,因为这现在只是一个字符串数组。

如果您想使用 then,您可以这样做:

Promise.all(...).then(urls => urls.map(...))

我希望这能回答您问题的基本方面。