简体   繁体   English

仅在 Javascript forEach/map 之后执行代码

[英]Execute code only after a Javascript forEach/map

I have a forEach function that loops through an array of files, uploads the file to Firebase Storage and then after the upload, it stores the image reference link into a array defined before.我有一个forEach函数,它循环遍历文件数组,将文件上传到 Firebase Storage,然后在上传后,它将图像引用链接存储到之前定义的数组中。

Process of each iteration:每次迭代的过程:

  • Take file object and convert to Blob获取文件对象并转换为 Blob
  • Upload Blob onto Firebase将 Blob 上传到 Firebase
  • After Blob uploads, receive a callback which has the image reference of the upload Blob 上传后,接收一个回调,其中包含上传的图像引用
  • Store the image reference in a list将图像参考存储在列表中

After the forEach , I use the list of image references for further processing.forEach ,我使用图像引用列表进行进一步处理。 However, when I try and reference the list, it is usually empty because this code executes before any images upload (and references are not recieved).但是,当我尝试引用该列表时,它通常是空的,因为此代码在任何图像上传之前执行(并且未收到引用)。 How can I use async/await with a Javascript forEach function where I can invoke my code to wait where it should expect a populated image reference list .如何将 async/await 与 Javascript forEach 函数一起使用,我可以在其中调用我的代码以等待它应该期待填充图像引用列表的位置 I've already tried to find a solution on stackoverflow but hasn't helped toward my solution.我已经尝试在 stackoverflow 上找到解决方案,但对我的解决方案没有帮助。

submitPost = async event => {

event.preventDefault();
const img_names = [];

this.state.files.forEach((ref_, index) => {
  ref_.current.getCroppedCanvas().toBlob(blob => {

    var uploadTask = this.storageRef
      .child("images/" + String(index))
      .put(blob);

    uploadTask.on(
      "state_changed",
      snapshot => {
        var progress =
          (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        console.log("Upload is " + progress + "% done");
      },
      error => {
        console.log(error);
      },
      () => {
        img_names.push(uploadTask.snapshot.ref.toString());
      }
    );
  });
console.log(img_names) // empty here
});

You can achieve that functionality by using map instead of forEach .您可以通过使用map而不是forEach来实现该功能。 Convert your array into an Array of Promises.将您的数组转换为 Promises 数组。 Then use that array inside a Promise.all() and await it.然后在Promise.all()使用该数组并等待它。

const promisifyUpload = (storageRef, ref_, index) => {
  return new Promise((resolve, reject) => {
    ref_.current.getCroppedCanvas().toBlob(blob => {

      var uploadTask = storageRef
        .child("images/" + String(index))
        .put(blob);

      uploadTask.on(
        "state_changed",
        snapshot => {
          var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
          console.log("Upload is " + progress + "% done");
        },
        error => console.log(error),
        () => resolve(uploadTask.snapshot.ref.toString())
      );

    });
  });

};

const submitPost = async event => {

  event.preventDefault();

  const img_names = await Promise.all(
    this.state.files.map((ref_, index) => promisifyUpload(this.storageRef, ref_, index))
  ));

  console.log(image_names); // Should now be filled
});

Edit : I split it up into 2 functions to show isolate the "promisify" logic编辑:我把它分成 2 个函数来显示隔离“promisify”逻辑

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM