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