如何等待 Firebase 存储图像上传,然后运行下一个函数

Posted

技术标签:

【中文标题】如何等待 Firebase 存储图像上传,然后运行下一个函数【英文标题】:How to wait for Firebase storage image upload, then run next function 【发布时间】:2020-07-09 14:47:56 【问题描述】:

我正在尝试编写一个函数,将多个图像上传到 Firebase,保存返回到对象的 URL,然后将该对象上传到我的 Cloud Firestore。我对 async/await 或 Promise 并没有真正的了解,所以如果有人可以提供帮助,将不胜感激。

基本上,我希望uploadImages() 完成运行,然后运行uploadData(),其中saveIssue() 在提交表单时被触发。

这是我正在使用的:

saveIssue() 
  this.uploadImages();
  this.uploadData();
,
uploadData() 
  let self = this;
  db.collection("issues")
    .add(self.issue)
    .then(docRef => 
      self.$router.push(
        name: "ReportPage",
        params:  issueId: docRef.id 
      );
    )
    .catch(error => 
      console.error(error);
    );
,
uploadImages() 
  const storageRef = storage.ref();
  let self = this;
  this.imagePreviews.forEach(image => 
    let imageName = uuidv1();
    let fileExt = image.fileName.split(".").pop();
    let uploadTask = storageRef
      .child(`images/$imageName.$fileExt`)
      .putString(image.base64String, "data_url");
    uploadTask.on("state_changed", 
      error: error => 
        console.error(error);
      ,
      complete: () => 
        uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => 
          self.issue.images.push(downloadURL);
        );
      
    );
  );
,

【问题讨论】:

【参考方案1】:

你必须使用 Promise,正如 here 解释的那样。你可以重写你的代码来支持异步等待,因为firebase支持它开箱即用,但一开始它可以是这样的:

async saveIssue() 
    await this.uploadImages();
    await this.uploadData();
  ,
  uploadData() 
    return new Promise((resolve, reject) => 
      let self = this;
      db.collection("issues")
        .add(self.issue)
        .then(docRef => 
          self.$router.push(
            name: "ReportPage",
            params: 
              issueId: docRef.id
            
          );
          resolve();
        )
        .catch(error => 
          console.error(error);
          reject(error);
        );
    )
  ,
  uploadImages() 
    return new Promise((resolve, reject) => 
      const storageRef = storage.ref();
      let self = this;
      this.imagePreviews.forEach(image => 
        let imageName = uuidv1();
        let fileExt = image.fileName.split(".").pop();
        let uploadTask = storageRef
          .child(`images/$imageName.$fileExt`)
          .putString(image.base64String, "data_url");
        uploadTask.on("state_changed", 
          error: error => 
            console.error(error);
            reject(error);
          ,
          complete: () => 
            uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => 
              self.issue.images.push(downloadURL);
              resolve();
            );
          
        );
      );
    )
  ,

【讨论】:

好的,这似乎是一个好的开始。它适用于 for each 中的第一个循环,但不适用于其余循环。有什么见解吗? 你需要查看 Promise.all,在这里阅读所有 async/await 的内容:javascript.info/async-await - 你基本上必须创建多个 Promise,然后一个一个地运行它 感谢您的回答。是否可以不创建此处所述的新承诺 (***.com/a/55806234/144088) 但仍监控上传状态?【参考方案2】:

好的,我找到了基于@AlexBrohshtut's answer 的解决方案。我仍然有一个问题,即第一个循环完成将允许等待继续,下面的代码似乎解决了这个问题。如果有人有更简洁的答案,很高兴更新! (我充其量是中级...)

 saveIssue() 
  Promise.all(
    this.imagePreviews.map(async image => 
      return await this.uploadImages(image);
    )
  ).then(() => 
    this.uploadData();
  );
,
uploadData() 
  let self = this;
  db.collection("issues")
    .add(self.issue)
    .then(docRef => 
      self.$router.push(
        name: "ReportPage",
        params: 
          issueId: docRef.id
        
      );
    )
    .catch(error => 
      console.error(error);
    );
,
uploadImages(image) 
  const storageRef = storage.ref();
  let self = this;
  return new Promise((resolve, reject) => 
    let imageName = uuidv1();
    let fileExt = image.fileName.split(".").pop();
    let uploadTask = storageRef
      .child(`images/$imageName.$fileExt`)
      .putString(image.base64String, "data_url");
    uploadTask.on("state_changed", 
      error: error => 
        console.error(error);
        reject(error);
      ,
      complete: () => 
        uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => 
          self.issue.images.push(downloadURL);
          resolve();
        );
      
    );
  );

【讨论】:

以上是关于如何等待 Firebase 存储图像上传,然后运行下一个函数的主要内容,如果未能解决你的问题,请参考以下文章

如何将图像上传到firebase存储然后将图像url存储在firestore中?

如何等待异步函数的结果? [复制]

等待HTTP请求内的Firebase存储调用以继续

将图像上传到 Firebase 存储后如何获取图像 uri?

Flutter - 将图像上传到 Firebase 存储

如何从输入字段将图像上传到 Firebase 云存储?