angular - 将异步传入图像上传到 Firebase 存储并等待所有要返回的 URL
问题描述
所以我是一个有角度的应用程序,它允许你将一些东西上传到云存储。比如说,标题、描述和一些图像。我将图像存储在 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 数组。它基本上冻结在承诺的某个地方。
解决方案
由于您对 Promise 更满意,因此您可以做一些事情,例如制作一组您的 observables,然后将它们组合起来。
const observables = [
...
];
return new Promise((resolve, reject) => {
Observable.combineLatest(observables).subscribe(
responses => {
// responses array will be in the same order as requests
console.log('responses:', responses);
resolve(responses);
},
error => {
console.log('error:', error);
reject(error);
}
);
});
编辑:我没有意识到这个包是如何工作的,试试这样的:
uploadImages(images, title) {
const urls: string[] = [];
return new Promise((resolve, reject) => {
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);
// in this case, all images should be done
if (urls.length === images.length) {
resolve(urls);
}
}));
}, error => {
console.log('resize failed, returning original images: ' + error);
reject(error);
});
});
}
推荐阅读
- django - 姜戈 | 不使用类别过滤问题
- java - 尝试对用户进行身份验证时发生内部错误。org..InternalAuthenticationServiceException:空
- firebase - 为什么我在 Android Studio 的 Flutter 项目中的 build.gradle 中出现此错误?
- python - Python 正则表达式不适用于给定的模式
- r - 在 R 中寻找合适的包进行聚类分析
- google-apps-script - 根据单元格值命名新工作表
- google-chrome-extension - Chrome 扩展程序:OAuth 验证请求问题
- mysql - 在mysql表中选择总和前10名
- python - 对于大型数组,是否有比 np.isin 更快的方法?
- reactjs - React 项目中自建模块的正确位置