【问题标题】:Async / await problem, The Async / await function is returning true before the value is placed in the new stateAsync / await 问题,Async / await 函数在值置于新状态之前返回 true
【发布时间】:2022-02-18 23:20:48
【问题描述】:

我正在使用 firebase 和 react-typescript 创建多图像文件上传。我的主要问题是异步/等待。我有一个名为 uploadFiles 的函数,它将下载的 URL 保存到我的 URLs 状态。但问题是uploadFiles 在 URL 仍在加载以设置为状态时返回 true。

我的期望是直到 setUrls 状态新值被放入 setUrls 状态 Async / await 不会返回 true。

我也在视频里解释过,https://youtu.be/t6JqasRCPRM

直播代码:https://codesandbox.io/s/eloquent-pine-tdv3wf?file=/src/AddProduct.tsx:2777-2941

主要问题在这里:setURLs 需要时间才能进入状态。

  async () => {
    await getDownloadURL(uploadTask.snapshot.ref).then((downloadURLs: any) => {
         setURLs((prevState: any) => [...prevState, downloadURLs])
         console.log("2 File available at", downloadURLs);
});

另外,另一个问题是当 URL 仍在加载以设置状态时,promise 会返回 true。

   try {
            await Promise.all(promises);
            setSuccess(true);
            return true;
        } catch (e) {
            console.error(e);
            return false;
        }

UploadFiles函数:

 const uploadFiles = async (files: any) => {

        const promises: any = []
        files.map((file: any) => {

            const sotrageRef = ref(storage, `files/${file.name}`);
            const uploadTask = uploadBytesResumable(sotrageRef, file);
            promises.push(uploadTask)
            uploadTask.on(
                "state_changed",
                (snapshot: any) => {
                    const prog = Math.round(
                        (snapshot.bytesTransferred / snapshot.totalBytes) * 100
                    );
                    setProgress(prog);
                },
                (error: any) => console.log(error),
                async () => {
                    await getDownloadURL(uploadTask.snapshot.ref).then((downloadURLs: any) => {
                        setURLs((prevState: any) => [...prevState, downloadURLs])
                        console.log("2 File available at", downloadURLs);

                    });
                }
            );


        })

        try {
            await Promise.all(promises);
            setSuccess(true);
            return true;
        } catch (e) {
            console.error(e);
            return false;
        }
    };

uploadWasSuccessful 正在返回我想要的 true,直到 setURls 可用我的 if 语句将不会进入下一步。

  const handleProductSubmit = async (e: any) => {
        e.preventDefault()

        const uploadWasSuccessful: any = await uploadFiles(images) // returning true but the urls are still loading.
        console.log('uploadWasSuccessful', uploadWasSuccessful);
        console.log('Success', success);

        if (uploadWasSuccessful) {
            const newProductValue = { ...productValue, URLs }
            console.log(newProductValue, 'productValue');
        }

    }

【问题讨论】:

  • uploadTask 不是一个承诺,所以当你将它推入 promises 数组时,你是在欺骗自己。
  • @trincot 所以我需要删除承诺?

标签: javascript reactjs firebase async-await es6-promise


【解决方案1】:

这里的 setSuccess(true) 调用不是异步的。这意味着它在 Promise 解决之前立即运行。在此处添加 await 以等待上述承诺解决。

try {
            await Promise.all(promises);
            await setSuccess(true); //await
            return true;
        } catch (e) {
            console.error(e);
            return false;
        }

还可以通过在此处包含 await 来做出上传承诺:

 const sotrageRef = ref(storage, `files/${file.name}`);
            const uploadTask = await uploadBytesResumable(sotrageRef, file); //added await
            await promises.push(uploadTask) //added await

【讨论】:

  • ` const sotrageRef = ref(storage, files/${file.name}); const uploadTask = await uploadBytesResumable(sotrageRef, file); //添加了await await promises.push(uploadTask)`它给了我在promise之前使用await的错误
【解决方案2】:

我通常使用的技巧是 uploadTask 它本身已经是一个承诺,所以你可以 await 它或链接它的 then,然后(至少)跳过第三个回调的方法:

const uploadFiles = async (files: any) => {

  const promises: any = []
  files.map((file: any) => {
    const storageRef = ref(storage, `files/${file.name}`);
    const uploadTask = uploadBytesResumable(storageRef, file);
    const urlTask = uploadTask.then(() => storageRef.getDownloadURL); // ?
    promises.push(urlTask); // ?
    uploadTask.on(
      "state_changed",
      (snapshot: any) => {
        const prog = Math.round(
          (snapshot.bytesTransferred / snapshot.totalBytes) * 100
        );
        setProgress(prog);
      },
      (error: any) => console.log(error),
      () => { } // ?
    );
  })

  try {
    const downloadURLs = await Promise.all(promises); // ?
    setURLs(downloadURLs); // ?
    setSuccess(true);
    return true;
  } catch (e) {
    console.error(e);
    return false;
  }
};

【讨论】:

  • 先生,downloadURLs 正在返回未定义
猜你喜欢
  • 2021-08-06
  • 1970-01-01
  • 2020-03-25
  • 2020-01-31
  • 1970-01-01
  • 2019-03-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
相关资源
最近更新 更多