【问题标题】:getDownloadURL takes some timegetDownloadURL 需要一些时间
【发布时间】:2022-01-27 22:59:49
【问题描述】:

我想通过附加在 ImageUrls 状态上的 getDownloadURL 来获取 url 返回,getDownloadURL 需要一两秒来返回 url,并且似乎代码继续运行并且不等待它返回 url

我正在尝试上传多张图片,然后在 Firestore 中创建一个包含图片网址和描述的对象


  const createAlbum = () => {
    addDoc(albumCollection, {
      name: albumName,
      category: category,
      images: imageUrls,
      description: description,
    });
  };

  const HandleUpload = (files) => {
    files.forEach((file) => {
      const storageRef = ref(
        storage,
        `/files/albums/${albumName}/${file.name}`
      );
      const uploadTask = uploadBytesResumable(storageRef, file);

      uploadTask.on(
        "state_changed",
        (snap) => {},
        (err) => {},
        () => {
          getDownloadURL(uploadTask.snapshot.ref).then((url) => {
            setImageUrls((prev) => [...prev, url]);
          });
        }
      );
    });
    createAlbum();

  };



【问题讨论】:

    标签: reactjs firebase firebase-storage


    【解决方案1】:

    获取下载 URL(如上传数据和大多数现代云 API)是一种异步操作。在处理此调用时,您的主代码确实会继续执行。然后当下载 URL 可用时,您的 then 回调将被调用,因此您可以使用它。

    因此,任何需要下载 URL 的代码都需要then 回调中,从那里调用,或者以其他方式同步。

    最简单的解决方法是将createAlbum 移动到then 回调中:

    uploadTask.on(
      "state_changed",
      (snap) => {},
      (err) => {},
      () => {
        getDownloadURL(uploadTask.snapshot.ref).then((url) => {
          setImageUrls((prev) => [...prev, url]);
          createAlbum();
        });
      }
    );
    

    如果您只想在所有上传完成后调用createAlbum(),您可以保留一个计数器或使用Promise.all()

    const HandleUpload = (files) => {
      let promises = files.map((file) => {
        const storageRef = ref(
          storage,
          `/files/albums/${albumName}/${file.name}`
        );
        return uploadBytesResumable(storageRef, file).then(() => {
          return getDownloadURL(uploadTask.snapshot.ref);
        });
      });
      Promise.all(promises).then((urls) => {
          setImageUrls(urls)
          createAlbum();
      })
    };
    

    这段代码利用uploadBytesResumable返回的任务也是Promise,所以我们可以通过then()知道什么时候完成,然后获取下载地址。

    请注意,如果 setImageUrlsuseState 钩子,则该操作也是异步的。我建议将图像 URL 显式传递给 createAlbum,而不是尝试通过状态传递,所以 createAlbum(urls)

    【讨论】:

      【解决方案2】:

      你也可以使用promise to error和callback来执行一次createAlbum()

      像这样:

      uploadTask.on(
        "state_changed",
        (snap) => {},
        (err) => {},
        (),
              error => {
                console.log('upload error: ', error.message)
              },
              () => {
                getDownloadURL(uploadTask.snapshot.ref).then((url) => {
        setImageUrls((prev) => [...prev, url]);
        createAlbum();
      });
              }
            )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-24
        • 2021-06-27
        • 2019-07-06
        • 2019-04-07
        • 2012-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多