Reputation: 9
var value = await this.upload();
if (value == true) {
this.item.photos = this.uploaded;
this.item.price = null;
this.item.qty = null;
this.dataSrv.addItem(this.item)
.then(() => {
this.dataSrv.stopLoading();
this.dataSrv.toast('Item Added Successfully');
this.item = {} as Item;
this.pictures = ['', '', '', ''];
this.uploaded = [];
this.photos = ['', '', '', ''];
})
.catch(err => {
this.dataSrv.stopLoading();
this.dataSrv.toast('Error While Adding Item. Try Again Later');
console.log(err);
});
}
In the above code I am calling upload function to upload picture to Google storage and I am waiting so I can add the image links to uploaded array which will save it to this.item.photos but It does not wait and it directly execute the true condition.
async upload(image?) {
var counter = 0;
this.pictures.forEach(i => {
if (i != '') {
let temp: string = (i) as string;
temp = temp.replace("data:image/jpg;base64, ", '');
temp = temp.replace("data:image/jpg;base64,", '');
temp = temp.replace('must use [property]=binding:', '');
temp = temp.replace('SafeValue', '');
temp = temp.replace('(see https://g.co/ng/security#xss)', '');
const randomId = Math.random().toString(36) + Math.random().toString(36) + Math.random().toString(36) + Math.random().toString(36);
const uploadTask = this.storage.ref('items/').child(randomId).putString(temp, 'base64', {
contentType: 'image/png'
});
uploadTask
.then(response => {
console.log("uploaded");
console.log(response);
this.storage.ref('items/' + randomId).getDownloadURL().subscribe(url => {
this.uploaded.push(url);
counter++;
});
})
.catch(err => {
console.log('not uploaded');
});
}
});
if (counter != this.uploaded.length) {
return false;
} else {
return true;
}
}
I have tried to do return type of Promise in the upload function but nothing changed I have also tried to do the then after the function call but the same issue happen
Note that pictures array contains base64 image
Upvotes: 1
Views: 230
Reputation: 997
async
functions will not block by themselves. The issue is that the forEach
is called synchronously, but it contains code which will run asynchrnously.
A common pattern for doing this:
async upload(image) {
// use .map instead of .forEach
// from the callback function we return a Promise, so the result would be
// an array of promises
const promises = this.pictures.map(i => {
// your logic here
// you must return the promise
return uploadTask
.then(response => { /* ... */ })
.catch(() => { /* ... */ });
})
// Wait for all promises to be resolved.
// Note for the future: Promise.all will reject if at least 1 promise rejects.
// Your code seems to handle this case and converts a failed Promise into a success inside of `.catch` above.
await Promise.all(promises);
// here, the counter should be correct
}
Upvotes: 2