so I'm an angular app that allows you to upload some stuff to Cloud Storage. say, a title, a description and some images. I am storing the images in firebase storage and then adding the download URLs to firebase aswell. I'm constructing a method that takes in an array of files, crops the images to a more usable size and then uploads those files to firebase storage:
uploadImages(images, title) {
const urls: string[] = [];
this.ng2ImgToolsService.resize(images, 700, 400).subscribe(result => {
const uploadImage = new File([result], result.name);
const path = `${title}/${Date.now()}_${uploadImage.name}`;
const ref = this.storage.ref(path);
const task = this.storage.upload(path, uploadImage);
task.snapshotChanges().pipe(tap(), finalize(async () => {
const url = await ref.getDownloadURL().toPromise;
urls.push(url);
}));
}, error => {
console.log('resize failed, returning original images: ' + error)
});
return urls;
}
this obviously doesn't work. I've also tried wrapping everything in a promise so i could do;
const urls = await this.uploadImages(...);
but at this point I have observables in observables in a promise, and I must admit that I'm in over my head. the times I've worked with async tasks they've been more straight forward.
I spend a couple more days reading up on RxJs but I'm afraid I can't figure it out on my own.
to summarize, this function needs to return an array of urls, I need to be able to await for this array, so basically wait with uploading everything to firestore until I have the download urls.
edit Alright after playing around with dockleryxk answer, I'm still running into some issues. First of all, the "ng2ImgToolsService.resize(images, 700, 400)" function takes in an array of images, and returns a promise that will pas through each cropped image, once it is done, in staid of all of them at once. So if I try to wrap this in a promise and resolve the output of this observable it will only return one image (whichever gets cropped first). So I'd have to wait for the observable to be done emitting data? Is this possible?
Secondly, if I indeed split everything up so that once I have an array of cropped images i'd put those images into a new function. In that function I'd have to loop over that array and upload them one by one.
uploadImages2(images, title) {
const observables = [];
for (let image of images) {
const path = `${title}/${Date.now()}_${image.name}`;
const ref = this.storage.ref(path);
const task = this.storage.upload(path, image);
task.snapshotChanges().pipe(tap(), finalize(async () => {
const url = ref.getDownloadURL();
observables.push(url);
}));
}
return new Promise((resolve, reject) => {
Observable.combineLatest(observables).subscribe(
responses => {
resolve(responses);
},
error => {
console.log('error:', error);
reject(error);
}
);
});
}
this does upload the images correctly but doesn't return the download url array. it basically freezes somewhere in the promise.