I have an input of type image which accepts multiple images. I save this in a React Hook and want to upload it to my Firebase Storage after the user presses Upload. For this I use a promise and an async method. Once the array of images has been traversed, I want to display some output in the log. However, React immediately jumps to the "Then" block for the console output, which of course is then NULL. What am I doing wrong ?
const uploadImg = async () => {
setUploadIsDone(false);
if (file.length) {
asyncFuncUploadToMongoDb().then((data) => {
console.log(data); // Is called immediately
setProgress(0);
setUploadIsDone(true);
});
}
};
const asyncFuncUploadToMongoDb = async () => {
const storage = getStorage();
return Promise.all(
file.map((f) => {
const articelImagesRef = ref(
storage,
"articelImg/" new Date() ".jpg"
);
const uploadTask = uploadBytesResumable(articelImagesRef, f);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
setProgress(progress);
// eslint-disable-next-line default-case
switch (snapshot.state) {
case "paused":
console.log("Upload is paused");
break;
case "running":
console.log("Upload is running");
break;
}
},
(error) => {
console.log(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setImgUrl([...imgUrl, downloadURL]);
});
}
);
})
);
};
CodePudding user response:
Inside your file.map method, you are not returning any promise.
You should return each promise from the map method, in order to handle all of them with Promise.all.
Since you have a listener callback (and not a promise for your task), you could create and return a brand new promise to handle each map finish.
Simple example based on your code (see comments)
return Promise.all(
file.map((f) => {
// Create and return a new Promise for each file
return new Promise((resolve, reject) => {
const articelImagesRef = ref(
storage,
"articelImg/" new Date() ".jpg"
);
const uploadTask = uploadBytesResumable(articelImagesRef, f);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
setProgress(progress);
// eslint-disable-next-line default-case
switch (snapshot.state) {
case "paused":
console.log("Upload is paused");
break;
case "running":
console.log("Upload is running");
break;
}
},
(error) => {
console.log(error);
// Reject the promise when fail
reject(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setImgUrl([...imgUrl, downloadURL]);
// Resolve the promise when ready
resolve(downloadUrl);
}).catch(error => {
// Reject the promise getting download url fail
reject(error);
});
}
);
});
})
);
