我正在尝试根据发送状态设置加载状态。如果图像被发送,我将简单地插入一个加载指示符。尽管每当任务运行时,我都会在任务真正完成之前收到一个done(.then(((,并且加载指示器没有按预期工作:
任务:
export async function storeImage(uri: string, description: string) {
const reference = ref(storage, `posts/${auth.currentUser!.uid}/${uuid.v4()}`);
const blob: any = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
console.log(e);
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', uri, true);
xhr.send(null);
});
const uploadTask: any = uploadBytesResumable(reference, blob);
uploadTask.on(
'state_changed',
(snapshot: any) => {
const progress = snapshot.bytesTransferred / snapshot.totalBytes;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case 'paused':
// console.log('Upload is paused');
break;
case 'running':
console.log('Upload is running');
break;
}
},
(error: any) => {
// Handle unsuccessful uploads
console.log('Storage error', error);
blob.close();
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then(async (downloadURL) => {
console.log('File available at', downloadURL);
await addImageReferenceToFirestore({ url: downloadURL, description });
});
blob.close();
}
);
}
如果我在const uploadTask: any = uploadBytesResumable(reference, blob);
上插入等待我收到了这个错误,它将永远加载:
[Unhandled promise rejection: TypeError: undefined is not a function (near '...uploadTask.on...')]
这是我的组件:
export function Post({ navigation, ...rest }: any) {
const [description, setDescription] = useState('');
const [loading, setLoading] = useState(false);
async function createPost() {
setLoading(true);
await storeImage(rest.route.params.images[0], description).then(() => console.log('done'));
setLoading(false);
}
return (
<Container>
{loading ? (
<Circle size={RFValue(25)} indeterminate={true} color="red" />
) : (
<CreateBar
text={i18n.t('createPost.title')}
iconName="CreatePost"
onPressIcon1={() => navigation.goBack()}
onPressIcon2={() => createPost()}
/>
)}
<ContainerDescription>
<ImageContainer>
<Image
source={{ uri: rest.route.params.images[0] }}
style={{ width: '100%', height: '100%', borderRadius: 8 }}
/>
</ImageContainer>
<TextAreaContainer>
<InputText
placeholder={i18n.t('createPost.describe')}
onChangeText={(newText: string) => setDescription(newText)}
/>
</TextAreaContainer>
</ContainerDescription>
<LightDivider />
在任务完成之前,您将收到来自console.log
的done
,因为您实际上并没有等待任务完成。您正在等待blob
部分。
如果你只想得到上传图像URL的最终结果,而不显示任何进度,那么你也应该等待uploadTask.on
完成。将uploadTask.on
包裹在Promise
中,resolve
成功上传图像,reject
出现错误:
await new Promise((resolve, reject) => {
uploadTask.on(
'state_changed',
(snapshot: any) => {
const progress = snapshot.bytesTransferred / snapshot.totalBytes;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case 'paused':
// console.log('Upload is paused');
break;
case 'running':
console.log('Upload is running');
break;
}
},
(error: any) => {
// Handle unsuccessful uploads
console.log('Storage error', error);
blob.close();
reject(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref)
.then(async (downloadURL) => {
console.log('File available at', downloadURL);
try {
await addImageReferenceToFirestore({ url: downloadURL, description });
} catch (err) {
reject(err);
}
resolve();
})
.catch((err) => reject(err));
blob.close();
},
);
});
您还应该在createPost
函数中添加一个try/catch/finally
块。否则,如果Promise
被拒绝,setLoading(false)
将永远不会被执行:
async function createPost() {
try {
setLoading(true);
await storeImage(rest.route.params.images[0], description);
} catch (err) {
console.error(err);
} finally {
setLoading(false);
}
}