如何在完成另一个函数时调用一个函数?
How to call a function on complition of another one?
我正在学习 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[];
}
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);
}
Post 对 Cloudinary API 的请求(在 for 循环中)是根据此 link 发出的:cloudinary docs
模态提交按钮触发 handleSaveEstate()。然后我想将所有图片上传到 Cloudinary 并从响应中获取 urls 到 arrray 并在调用 addEstate(urls) 时完成。
首先调用 Friebase,然后填充数组:
如何按顺序拨打这些电话?
这里有多个问题。
- 循环内的订阅可能会导致多个打开的订阅。相反,您可以将 RxJS
forkJoin
与 Array#map
. 一起使用
- 您不能从异步调用中同步 return
urls
。您需要 return observable 并在需要响应的地方订阅。
- 您可以使用 RxJS
from
函数将 promise 转换为函数。您要么需要将 promise 转换为 observable,反之亦然。我已经使用 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)
);
})
);
}
我正在学习 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[];
}
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);
}
Post 对 Cloudinary API 的请求(在 for 循环中)是根据此 link 发出的:cloudinary docs
模态提交按钮触发 handleSaveEstate()。然后我想将所有图片上传到 Cloudinary 并从响应中获取 urls 到 arrray 并在调用 addEstate(urls) 时完成。
首先调用 Friebase,然后填充数组:
如何按顺序拨打这些电话?
这里有多个问题。
- 循环内的订阅可能会导致多个打开的订阅。相反,您可以将 RxJS
forkJoin
与Array#map
. 一起使用
- 您不能从异步调用中同步 return
urls
。您需要 return observable 并在需要响应的地方订阅。 - 您可以使用 RxJS
from
函数将 promise 转换为函数。您要么需要将 promise 转换为 observable,反之亦然。我已经使用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)
);
})
);
}