我最近开始学习打字稿,到目前为止,我一直很喜欢!当前正在尝试制作一个具有个人资料页面且具有更改个人资料图片功能的网络应用。
我有一个将图片上传到Firebase的功能,称为 store ,还有一个功能,它从Firebase下载了图片,其名称为 displayImage 。这两个函数都获得参数photoType,该参数指示我们是要更改封面照片还是个人资料照片。
它的工作方式是,我知道它调用了存储函数,并且在打开文件选择器之前,它提醒我它调用了displayImage函数。它并行运行,并且完成的第一个功能是displayImage,它将用Firebase存储中当前存在的图像更新我的当前配置文件图像,然后将其上载到Firebase。
我收到的最后一个警报是“上传成功”,这不是我想要的方案。
代码如下:
diplayActionSheet(){
const actionSheet = this.actionSheetCtrl.create({
title: 'Select preferred action',
buttons: [
{
text: 'Change profile picture',
handler: () => {
this.uploadAndDisplay("profile");
}
},{
text: 'Change cover photo',
handler: () => {
this.uploadAndDisplay("cover");
}
},{
text: 'Cancel',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}
]
});
actionSheet.present();
}
async uploadAndDisplay(photoType){
await this.store(photoType);
await this.displayImage(photoType);
}
store(photoType) {
alert("Uslo u store sa parametrom photoType: " +photoType);
this.fileChooser.open().then((url) => {
(<any>window).FilePath.resolveNativePath(url, async (result) => {
alert("Pre nego sto udje u uploadImage");
this.nativepath = result;
await this.uploadImage(photoType);
}
)
})
return Promise.resolve("test");
}
uploadImage(photoType) {
alert("Uslo u uploadImage sa parametrom photoType: " +photoType);
let imageName=this.angularFireAuth.auth.currentUser.uid+"__"+photoType;
alert("imageName: " +imageName);
(<any>window).resolveLocalFileSystemURL(this.nativepath, (res) => {
res.file((resFile) => {
var reader = new FileReader();
reader.readAsArrayBuffer(resFile);
reader.onloadend = (evt: any) => {
var imgBlob = new Blob([evt.target.result], { type: 'image/jpeg' });
imgBlob
//
var imageStore = this.firestore.ref().child("images/"+imageName); //firestore = firebase.storage();
imageStore.put(imgBlob).then((res) => {
alert('Upload Success');
}).catch((err) => {
alert('Upload Failed' + err);
})
}
})
})
}
async displayImage(photoType){
alert("pozvana funkcija: displayImage()");
let imageName=this.angularFireAuth.auth.currentUser.uid+"__"+photoType;
this.profileImgURL=this.angularFireAuth.auth.currentUser.uid+"__profile";
alert("imageName==this.profileImgURL:" +imageName==this.profileImgURL);
this.firestore.ref().child("images/"+this.profileImgURL).getDownloadURL().then((url) => {
alert("displayImage");
this.zone.run(()=>{
alert("displayImage 2");
var picElem = <HTMLImageElement>document.getElementById('myimg');
alert("posle this.element = document.getElementById('myimg');");
console.log("this.element: "+picElem);
alert("this.element: "+picElem);
picElem.src = url;
})
})
我了解到我可能正在使用关键字async并等待错误,但是我无法真正找出使用它们的正确方法。来自Java,这对我来说有点奇怪。 这两个函数(store和displayImage)都可以很好地独立运行,如果我只按一个刷新按钮,但我真的不想要那样,我可以使它正常工作。
希望大家能提前帮助我,加油并感谢!
答案 0 :(得分:1)
您正在将某些函数声明为async
,但没有使用await
来使它们在继续执行之前等待promise返回。例如,在功能displayImage
中,您具有以下代码段:
this.firestore.ref().child("images/"+this.profileImgURL).getDownloadURL().then((url) => {...}
这将做的是创建诺言,该诺言由getDownloadURL返回,然后继续到下一行,在本例中,这是函数的结尾,因此该函数将在诺言解析(完成)之前退出。在将来的某个时候,promise将会解决,然后将执行.then
回调,但是到那时函数已经退出。
要等待完成,可以将其更改为:
const url = await this.firestore.ref().child("images/"+this.profileImgURL).getDownloadURL();
这将使函数等待getDownloadURL
返回的promise的返回,然后再继续执行函数的下一行,即结束。
在代码中的其他地方也会发生这种情况,但是我希望这种解释足够了,以便您也可以应用相同的技术。