问题描述
我想做一个函数,将从 react-native-image-picker 中选取的照片上传到 firestore,然后返回上传图像的 URL 值。照片上传成功,我可以在控制台中打印下载 URL,问题是当我尝试在函数中返回 URL 时,它是未定义的。我尝试使用异步函数在返回值之前等待图像选择器响应完成,但它仍然返回 {"_U": 0,"_V": 0,"_W": null,"_X": null} .
uploadImg: async () =>{
await ImagePicker.launchImageLibrary({ mediaType: 'photo' },response => {
if (response.error) {
alert('Something went wrong');
} else {
try {
const { path,uri } = response;
const fileSource = Platform.OS === 'android' ? uri : path;
const { fileName } = response;
const storageRef = storage().ref(fileName);
storageRef.putFile(fileSource).on('state_changed',snapshot => {
switch (snapshot.state) {
case 'running':
setimageURI(null);
break;
case 'success':
snapshot.ref.getDownloadURL().then(downloadURL => {
setimageURI(downloadURL);
//This console log works,and actually prints the correct url
console.log(`Download URL ${downloadURL}`);
});
break;
default:
break;
}
});
} catch (error) {
console.log(error)
}
}
});
return imageURI;
}
我很确定问题不在于状态、上传图片或图像选择器响应。这可能是异步函数的错误用法。
解决方法
async/await 的一个非常基本的用法是这样的:
const someCuteAsyncFunc = async () => {
try {
let promise = new Promise((resolve,reject) => {
setTimeout(() => resolve("done!"),1000)
});
let result = await promise; // wait until the promise resolves (*)
alert(result); // "done!"
} catch (error) {
console.error(error);
}
}
基于this example。
鉴于您的代码、try/catch、if/else、switch 和最后的 return,我认为您需要首先简化函数以确保从 Promise 返回图像。关于这个话题 here 有一个很好的答案。
,这是因为您在 firebase 调用完成执行之前从函数返回。我对您的代码进行了一些更新,以便该函数可以等待 Firebase 响应。
uploadToFirebase: ( fileName,filesource )=>new Promise((resolve,reject)=>{
const storageRef = storage().ref(fileName);
storageRef.putFile(fileSource).on('state_changed',snapshot => {
switch (snapshot.state) {
case 'running':
setImageURI(null);
break;
case 'success':
snapshot.ref.getDownloadURL().then(downloadURL => {
setImageURI(downloadURL);
//This console log works,and actually prints the correct url
console.log(`Download URL ${downloadURL}`);
});
break;
default:
break;
}
resolve();
});
})
uploadImg: async () =>{
let response = await ImagePicker.launchImageLibraryAsync({ mediaType: 'photo' });
if (response.error) {
alert('Something went wrong');
} else {
const { path,uri } = response;
const fileSource = Platform.OS === 'android' ? uri : path;
const { fileName } = response;
await uploadToFirebase(fileName,fileSource)
}
return imageURI;
}