我正在使用firebase和react typescript创建一个多图像文件上传。我的主要问题是async/await。我有一个名为uploadFiles
的函数,它将把下载的URL保存到我的URLs
状态。但问题是uploadFiles
返回true,而URL仍在加载以设置为该状态。
我的期望是,直到setUrls
状态将新值放入setUrls
状态,Async/await才会返回true。
我也在视频中解释过,https://youtu.be/t6JqasRCPRM
实时代码:https://codesandbox.io/s/eloquent-pine-tdv3wf?file=/src/AddProduct.tsx:2777-2941
主要问题是:setURLs
需要时间才能设置到状态。
async () => {
await getDownloadURL(uploadTask.snapshot.ref).then((downloadURLs: any) => {
setURLs((prevState: any) => [...prevState, downloadURLs])
console.log("2 File available at", downloadURLs);
});
另外,另一个问题是promise返回true,而URL仍在加载以设置为状态。
try {
await Promise.all(promises);
setSuccess(true);
return true;
} catch (e) {
console.error(e);
return false;
}
UploadFiles
功能:
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
返回true,我希望在setURls可用之前,我的if语句不会进入下一步。
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');
}
}
try {
await Promise.all(promises);
await setSuccess(true); //await
return true;
} catch (e) {
console.error(e);
return false;
}
还通过在这里包括等待做出上传承诺:
const sotrageRef = ref(storage, `files/${file.name}`);
const uploadTask = await uploadBytesResumable(sotrageRef, file); //added await
await promises.push(uploadTask) //added await
我通常使用的技巧是,uploadTask
本身已经是一个承诺,所以你可以await
它或链接它的then
,只需跳过(至少(第三个回调的方法:
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;
}
};