等待不等待异步函数返回值

时间:2020-09-04 12:55:33

标签: javascript reactjs async-await firebase-storage

我正在使用firebase进行反应,我需要将一些图片上传到firebase存储器,然后保存从上载函数返回的下载网址,以将该值存储在firestore中。

这是我的图片上传功能

const imageUpload = async (image) => {
    const uploadTask = storage.ref(`images/${image.name}`).put(image);
    uploadTask.on(
      'state_changed',
      (snapshot) => {},
      (error) => {
        console.log(error);
      },
      () => {
        storage
          .ref('images')
          .child(image.name)
          .getDownloadURL()
          .then((url) => {
            setImageUrl(url);
            console.log(url);
            return url;
          });
      }
    );
  };

这是我的提交处理程序

const handleSubmit = async (e) => {
    e.preventDefault();

    let entry = {
      author: currentUser.email,
      body,
    };
    if (image) {
      await imageUpload(image).then(async (url) => {
        console.log(url);
        entry = {
          author: currentUser.email,
          body,
          imageUrl,
        };
        try {
          await createEntry(entry).then(() => {
            setBody('');
            setShowSnackbar(true);
          });
        } catch (error) {
          console.log(error);
        }
      });
    } 

    try {
      await createEntry(entry).then(() => {
        setBody('');
        setShowSnackbar(true);
      });
    } catch (error) {
      console.log(error);
    }
  };

但是这不起作用,因为控制台首先显示undefined,然后显示url,这意味着await不在等待返回url。我该如何解决?

2 个答案:

答案 0 :(得分:2)

问题主要是因为等待,然后一起使用。 通过将代码转换为仅使用await可以有所帮助。

想象一个场景,其中function c对异步function a的调用解析时会调用function b

const a = () => {
     b().then(() => c());
};

这是使用async / await而不是promise编写的相同程序:

const a = async () => {
    await b();
    c();
};

因此,您的图片上传逻辑类似于下面的代码,您可以转换其余代码:

const url = await imageUpload(image)
console.log(url);
entry = {
  author: currentUser.email,
  body,
  imageUrl,
};

和imageUpload函数看起来像

async function imageUpload(image) {
  try {
    const storageRef = firebase.storage().ref();
    // Create the file metadata
    const metadata = {     contentType: "image/jpeg" };
    const fileRef = storageRef.child(`${this.name}/` + image.name);
    const uploadTaskSnapshot = await fileRef.put(file, metadata);
    const downloadURL = await uploadTaskSnapshot.ref.getDownloadURL();
    setImageUrl(url);
    console.log(url);
    return downloadURL;
 } catch (error) {
    console.log("ERR ===", error);
 }
}

答案 1 :(得分:1)

我想你在混东西。

如果您正在使用async / await,则无需在您的诺言中使用then

使用async / await习惯用法,您的代码应看起来更像

async function handleSubmit(e) {
  e.preventDefault();

  let entry = {
    author: currentUser.email,
    body,
  };

  if (image) {
    const url = await imageUpload(image);
    entry = {
      author: currentUser.email,
      body,
      imageUrl,
    };
    try {
      await createEntry(entry);
      setBody("");
      setShowSnackbar(true);
    } catch (error) {
      console.log(error);
    }
  }

  try {
    await createEntry(entry);
    setBody("");
    setShowSnackbar(true);
  } catch (error) {
    console.log(error);
  }
}

async function imageUpload(image) {
  const uploadTask = storage.ref(`images/${image.name}`).put(image);
  return new Promise((resolve, reject) => {
    uploadTask.on(
      "state_changed",
      (snapshot) => {},
      (error) => {
        reject(error);
      },
      () => {
        storage
          .ref("images")
          .child(image.name)
          .getDownloadURL()
          .then((url) => {
            setImageUrl(url);
            resolve(url);
          });
      }
    );
  });
}

async/await实际上是为了使编程以某种“感觉”同步的方式实现。除了代码无法正常工作之外,使用then和callbacks会使它没有从语法中受益。

请参阅https://developer.mozilla.org/fr/docs/Learn/JavaScript/Asynchronous/Concepts