简体   繁体   中英

await not waiting for async function to return value

I'm using react with firebase where I need to upload some pictures to firebase storage and then save the download url that gets returned from the upload function to store that value on firestore.

This is my image uploading function

 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; }); } ); };

And this is my on submit handler

 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); } };

However this doesn't work because the console shows undefined first and then the url which means that the await is not waiting for the url to be returned. How do i resolve this?

The issue is primarily because of await and then are used together. By converting your code to use await only can help.

Imagine a scenario where a function c is called when function a call to an asynchronous function b resolves:

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

Here's the same program, written using async/await instead of promise:

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

So your logic of image upload can look like code below and you can convert rest of the code:

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

and the imageUpload function can look like,

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);
 }
}

I think you are mixing things.

You don't need to use then on your promises if you are using async / await

Using the async/await idiom your code should look more like

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 is actually intended to make programming with promises somehow 'feel' synchronous. Using then and callbacks, beside the fact that the code would not work, makes it taking no benefit from the syntax.

see https://developer.mozilla.org/fr/docs/Learn/JavaScript/Asynchronous/Concepts

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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