【问题标题】:How to wait for Firebase storage image upload, then run next function如何等待 Firebase 存储图像上传,然后运行下一个函数
【发布时间】: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);
        });
      }
    });
  });
},

【问题讨论】:

    标签: javascript firebase vue.js promise firebase-storage


    【解决方案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,然后一个一个地运行它
    • 感谢您的回答。是否可以不创建此处所述的新承诺 (stackoverflow.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();
            });
          }
        });
      });
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 1970-01-01
      • 2019-07-24
      • 2022-11-17
      • 1970-01-01
      相关资源
      最近更新 更多