【发布时间】:2019-11-08 16:29:46
【问题描述】:
所以我是一个 Angular 应用程序,它允许您将一些内容上传到 Cloud Storage。比如说,标题、描述和一些图像。我将图像存储在 firebase 存储中,然后也将下载 URL 添加到 firebase。我正在构建一个接收文件数组的方法,将图像裁剪为更可用的大小,然后将这些文件上传到 Firebase 存储:
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;
}
这显然行不通。我还尝试将所有内容都包装在一个承诺中,这样我就可以做到;
const urls = await this.uploadImages(...);
但在这一点上,我在 promise 中的 observables 中有 observables,我必须承认我已经过头了。在我处理异步任务的时候,它们更加直截了当。
我又花了几天时间阅读 RxJs,但恐怕我自己无法弄清楚。
总而言之,这个函数需要返回一个url数组,我需要能够等待这个数组,所以基本上等待上传所有内容到firestore,直到我有下载url。
编辑 好吧,在玩了 dockeryxk 答案之后,我仍然遇到了一些问题。首先,“ng2ImgToolsService.resize(images, 700, 400)”函数接收一个图像数组,并返回一个承诺,一旦完成,将通过每个裁剪的图像,而不是一次所有的图像.因此,如果我尝试将其包装在一个 Promise 中并解析此 observable 的输出,它将仅返回一个图像(以先裁剪的为准)。所以我必须等待 observable 完成发射数据?这可能吗?
其次,如果我确实拆分了所有内容,以便在拥有一组裁剪图像后,我会将这些图像放入一个新函数中。在该函数中,我必须遍历该数组并一一上传。
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);
}
);
});
}
这确实会正确上传图像,但不会返回下载 url 数组。它基本上冻结在承诺的某个地方。
【问题讨论】:
标签: angular typescript firebase asynchronous rxjs