Reputation: 25
I've recently got into learning typescript and I love it so far! Currently trying to make a web app that has a profile page that has a functionality to change a profile picture.
I have a function that uploads the picture to the firebase called store, and I also have a function that downloads it from firebase called displayImage. Both those functions get the parameter photoType that indicates whether we are changing cover photo or profile photo.
The way it works out is that I get that it calls the store function, and before it opens the file chooser it alerts me that it called the displayImage function. It goes parallel and the first function to finish is displayImage, which updates my current profile image with an image that's currently in the firebase storage, and afterwards it uploads my chosen image to the firebase.
The last alert I get is the "Upload success", which is not the scenario I am aiming for.
Here's the code:
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;
})
})
I understand that I'm probably using the keywords async and await wrong, but I can't really figure out the correct way to use them. Coming from Java, this all is a bit strange for me. Both functions (store and displayImage) are working perfectly fine standalone, and I can get this to work if I just make a refresh button but I don't really want it like that.
Hope you people can help me, cheers and thanks a lot in advance!
Upvotes: 0
Views: 443
Reputation: 3139
You are declaring some functions as async
but aren't using await
for make them wait for promises to return before continuing the execution. For example, in the function displayImage
you have this block:
this.firestore.ref().child("images/"+this.profileImgURL).getDownloadURL().then((url) => {...}
What this will do is create the promise, which is returned by getDownloadURL, and then continue to the next line, which in this case is the end the function, so the function will exit before the promise resolves (completes). At some point in the future the promise will resolve and then the .then
callback will be executed, but at that point the function has already exited.
To wait for it to finish you can change it to:
const url = await this.firestore.ref().child("images/"+this.profileImgURL).getDownloadURL();
This will make the function await the return of the promise returned by getDownloadURL
, and only then continue to the next line on the function, which is the end.
There are other points in your code in which this also happens, but I hope this explanation was enough so that you can also apply the same technique.
Upvotes: 1