我正在通过建立一个小型房地产代理作为宠物项目来学习 Angular。我有一个带有表单的模式,用户可以在其中添加新的 Estate - 基本数据和图片。首先,我想将其保存到 Cloudinary,然后将网址保存到 Firebase。
我无法让它按顺序运行,而是首先使用空的 urls 数组调用 Firebase。我发现 rxjs 中有函数 finalize() 但它也不起作用。
云服务:
uploadImage(vals: any): Observable<any>{
return this.http
.post('https://api.cloudinary.com/v1_1/<my_cloudinary>/image/upload', vals)
}
FirebaseService 和 IEstate:
addEstate(estate: IEstate){
return this.firestore.collection('estate').doc().set(estate);
}
export interface IEstate{
id?: string;
city: string;
street: string;
links: string[];
}
EstateCreateComponent:
form: FormGroup;
estates: IEstate[] = [];
files: File[] = [];
handleSaveEstate(){
let result : string[];
this.uploadToCloudinary()
.pipe(
finalize(() => this.addEstate(result)))
.subscribe(res => result = res,
error =>{
console.log(error);
},
() => {
console.log('complete')
});
}
addEstate(links: string[]): void{
let data = {
city: this.form.value.city,
street: this.form.value.street,
links: links
} as IEstate;
this.firebaseService.addEstate(data).then((res) =>{
console.log(res);
});
}
uploadToCloudinary(){
const data = new FormData();
let urls: string[] = [];
for (let i = 0; i < this.files.length; i++) {
data.append('file', this.files[i]);
data.append('upload_preset', 'my_name_upload')
data.append('cloud_name', 'my_cloudinary_name')
this.cloudinary.uploadImage(data).subscribe(res =>{
urls.push(res.secure_url);
});
}
return of(urls);
}
根据此链接向 Cloudinary API 发布请求(在 for 循环中):cloudinary docs
模态提交按钮触发 handleSaveEstate()。然后我想将所有图片上传到 Cloudinary 并从响应中获取 url 到 arrray 并在调用 addEstate(urls) 时完成。
首先调用 Friebase,然后填充数组:
如何按顺序拨打这些电话?
答案 0 :(得分:2)
这里有多个问题。
forkJoin
与 Array#map
结合使用。urls
。您需要返回 observable 并在需要响应的地方订阅。from
函数将承诺转换为函数。您要么需要将承诺转换为可观察的,反之亦然。我已经使用 from
对前者进行了说明。switchMap
等映射运算符从一个 observable 切换到另一个。试试下面的方法
form: FormGroup;
estates: IEstate[] = [];
files: File[] = [];
handleSaveEstate() {
let result: string[];
this.uploadToCloudinary().pipe(
switchMap(urls => this.addEstate(urls))
).subscribe({
next: (res) => {
console.log(res); // <-- response from `this.firebaseService.addEstate()`
},
error: (error) => {
console.log(error);
},
complete: () => {
console.log('complete')
}
});
}
addEstate(links: string[]): Observable<any> {
let data = {
city: this.form.value.city,
street: this.form.value.street,
links: links
} as IEstate;
from(this.firebaseService.addEstate(data));
}
uploadToCloudinary(): Observable<any> {
const data = new FormData();
return forkJoin(
this.files.map(file => {
data.append('file', file);
data.append('upload_preset', 'my_name_upload')
data.append('cloud_name', 'my_cloudinary_name')
return this.cloudinary.uploadImage(data).pipe(
map(res => res.secure_url)
);
})
);
}