'Async / await problem, The Async / await function is returning true before the value is placed in the new state
I am creating a multiple image file upload using firebase and react-typescript. My main problem is with async/await. I have a function called uploadFiles which will save the downloaded URLs into my URLs state. But the problem is uploadFiles returning true while the URLs are still loading to set into the state.
My expectation is until setUrls state new values are placed into the setUrls state the Async / await will not return true.
I have explained in the video also, https://youtu.be/t6JqasRCPRM
Live code: https://codesandbox.io/s/eloquent-pine-tdv3wf?file=/src/AddProduct.tsx:2777-2941
The main problem is here: setURLs are taking time to set into the state.
async () => {
await getDownloadURL(uploadTask.snapshot.ref).then((downloadURLs: any) => {
setURLs((prevState: any) => [...prevState, downloadURLs])
console.log("2 File available at", downloadURLs);
});
Also, another problem is that promise is returning true while the URLs are still loading to set into the state.
try {
await Promise.all(promises);
setSuccess(true);
return true;
} catch (e) {
console.error(e);
return false;
}
UploadFiles function:
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 is returning true I want until the setURls is available my if statement will not go to the next step.
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');
}
}
Solution 1:[1]
The setSuccess(true) call here is not asynchronous. This means its running immediately before the promises are resolved. Add await here to wait for the promises to resolve above.
try {
await Promise.all(promises);
await setSuccess(true); //await
return true;
} catch (e) {
console.error(e);
return false;
}
also make the uploads promises by including await here:
const sotrageRef = ref(storage, `files/${file.name}`);
const uploadTask = await uploadBytesResumable(sotrageRef, file); //added await
await promises.push(uploadTask) //added await
Solution 2:[2]
The trick I normally use is that the uploadTask it itself a promise already, so you can await it or chain its then, and just skip the approach with (at least) the third callback:
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;
}
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | tempnameenjoyer |
| Solution 2 | Frank van Puffelen |
