angular - 如何在编译另一个函数时调用一个函数?
问题描述
我正在通过建立一个小型房地产中介作为宠物项目来学习 Angular。我有一个表单,用户可以在其中添加新的 Estate - 基本数据和图片。首先,我想将其保存到 Cloudinary,然后将 url 保存到 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[];
}
房地产创建组件:
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
Modal submit button triggers handleSaveEstate()。然后我想将所有图片上传到 Cloudinary 并从对数组的响应中获取 url,并在调用 addEstate(urls) 时获取。
首先调用 Friebase,然后填充数组:
我如何按顺序拨打这些电话?
解决方案
这里有多个问题。
- 循环内的订阅可能会导致多个开放订阅。相反,您可以将 RxJS
forkJoin
与Array#map
. - 您不能
urls
从异步调用中同步返回。您需要返回 observable 并在需要响应的地方订阅。 - 您可以使用 RxJS
from
函数将 Promise 转换为函数。您要么需要将承诺转换为可观察的,反之亦然。我已经用from
. - 使用映射运算符喜欢
switchMap
从一个可观察对象切换到另一个。
尝试以下
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)
);
})
);
}
推荐阅读
- python - Matplotlib FuncAnimation 视频质量差
- ios - 在 viewContext 上使用 perform 方法和不使用 perform 方法有什么区别?- 核心数据
- node.js - 无法使用socket.io,参考错误:io未定义
- python - 如何使用简单的 jwt django rest 框架实现 httponly jcookies
- c# - 如何将 tokenModel.ExpiresIn 转换为秒
- swift - 异步加载数据
- java - 我想确认收到的 json 数据
- sql - 在 SQL 上获取值“0”和“1”交替行
- mongodb - 按分层数组分组并获取每个级别的计数
- python - 在 Django 中返回 False 的表单验证