代码之家  ›  专栏  ›  技术社区  ›  AndreaNobili

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

  •  0
  • AndreaNobili  · 技术社区  · 5 年前

    我是JavaScript技术和RxJS的新手,我对这段代码的确切工作原理有以下疑问。它取自我正在进行的一个项目,它工作得很好,但我需要了解它到底是如何工作的 Promise.all() 工作原理以及如何在这段代码中使用它。

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

    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() 方法接收 文件列表 参数,是用户上传的必须保存在Firebase存储上的文件列表。保存文件后,我必须存储文件的URL。

    为了保存这些文件,使用 uploadFileIntoFirebaseStore() 方法返回a 承诺[] 因此,它返回一个包含n个Promise对象的数组。

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

    1. 它可以解析为字符串数组(其中每个字符串表示Firebase Storage上上传文件的URL)。
    2. 如果发生错误,将被拒绝(我认为如果文件上传失败,也可能会发生这种情况)。

    所以根据我对使用的理解 Promise.all() 方法是,在我的数组的所有promise都被解析之后,它会做一些事情。在我的代码中,我有:

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

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

    第二个疑问与 等待 Promise.all()方法前面的关键字。这意味着这是一个 async 方法?据我所知 等待 关键字只能与async方法一起使用。

    最后一个疑问是:在查看各种教程和文档时,我发现通常是这样的:

    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()方法作为数组,然后我有 然后() 当数组的所有promise对象都被解析时,执行箭头函数的方法(我也可以让catch()方法在被拒绝的情况下做点什么)。

    这与我的代码大不相同,我没有 然后() 当我所有的承诺都得到解决时,做某事的方法。相反,我的代码使用RxJS map() 操作符在(已解决?)promise列表中。

    据我所知,这个map()运算符迭代返回的包含相关文件url的已解析promise,以便在控制台中打印它并将其作为Observable返回(在我看来,map()总是返回Observable,对吗?)

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

    0 回复  |  直到 5 年前
        1
  •  1
  •   Harley Thomas    5 年前

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

    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(...))
    

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

        2
  •  1
  •   venkatesh pogartha    5 年前

    承诺。全部

    它将获取一组promise并并行执行它们。 它遵循以下机制 全部或无

    Promise.all([…]).then(console.log) 如果所有promise都是 完成了 ,否则将执行catch Promise.all([…]).catch(console.log)

    还有一种方法 Promise.all已解决 即使其中一个承诺失败了,这也将被视为成功。返回数据包含所有带有状态的结果

    语法:-

    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);
    
    推荐文章