Angular 使用第二个API的observable存在问题
在这里,我对RxJs非常不好,我面临一个问题 在我的一个角度分量中,我加载如下数据:Angular 使用第二个API的observable存在问题,angular,typescript,rxjs,observable,store,Angular,Typescript,Rxjs,Observable,Store,在这里,我对RxJs非常不好,我面临一个问题 在我的一个角度分量中,我加载如下数据: this._obs$.push(this.store1.loadTypes()); this._obs$.push(this.store2.loadLimitQuantities()); // [...] forkJoin(this._obs$).subscribe( next => console.log(next), error => console.log(error) );
this._obs$.push(this.store1.loadTypes());
this._obs$.push(this.store2.loadLimitQuantities());
// [...]
forkJoin(this._obs$).subscribe(
next => console.log(next),
error => console.log(error)
);
其中一个可观察对象从API 1接收数据,然后需要从API 1接收的数据中从API 2检索数据:
loadLimitQuantities(): Observable<LimitQuantity[]> {
// API 1
const obs = this.limitQuantityService.getLimitQuantities().pipe(share());
obs.subscribe(data => {
if (data) {
const ifs = [];
data.forEach(element => {
// API 2
ifs.push(this.technicalAttribTextIFSService.getType(element.ifsType).pipe(take(1), tap((type) => {
type ? element.type = type.valueText : element.type = null;
})));
});
forkJoin(ifs).subscribe(end => {
this.limitQuantitiesSubject.next(data);
});
} else {
console.error("Erreur lors du chargement des quantités limites");
}
});
// AP1
return obs;
}
loadLimitQuantilities():可观察{
//API 1
const obs=this.limitQuantityService.getLimitQuantilities().pipe(share());
obs.subscribe(数据=>{
如果(数据){
常数ifs=[];
data.forEach(元素=>{
//API 2
ifs.push(this.technicalAttribTextIFSService.getType(element.ifsType).pipe(take(1),tap((type)=>{
类型?element.type=type.valueText:element.type=null;
})));
});
forkJoin(ifs).订阅(end=>{
this.limitQuantiesSubject.next(数据);
});
}否则{
控制台错误(“数量限制收费错误”);
}
});
//AP1
返回obs;
}
不幸的是,加载数据的角度组件的下一个
接收得太早,因为API 1已完成返回数据,而不是API 2
怎么办?返回的应该位于API 2的forkJoin
StackBlitz:
谢谢你的帮助。也许你需要这样的东西
class MyClass {
loadLimitQuantities(): Observable < LimitQuantity[] > {
// API 1
return this.limitQuantityService.getLimitQuantities().pipe(
map((data) => this.getTypeRequests(data)),
switchMap((requests) => forkJoin(requests))
);
}
getTypeRequests(data) {
if(!data) {
console.error("Erreur lors du chargement des quantités limites");
return [];
}
return data.map(element => this.getType(element));
}
getType(element) {
return this.technicalAttribTextIFSService.getType(element.ifsType)
.pipe(map((type) => ({...element, type: type ? type.valueText : null})))
}
}
class-MyClass{
LoadLimitQuantilities():可观察的{
//API 1
返回此.limitQuantityService.GetLimitQuantilities()管道(
map((数据)=>this.getTypeRequests(数据)),
switchMap((请求)=>forkJoin(请求))
);
}
getTypeRequests(数据){
如果(!数据){
控制台错误(“数量限制收费错误”);
返回[];
}
返回data.map(元素=>this.getType(元素));
}
getType(元素){
返回此.technicalAttribTextIFSService.getType(element.ifsType)
.pipe(映射((类型)=>({…元素,类型:type?type.valueText:null})))
}
}
您可以得到限制数量,将它们映射到类型请求,然后将它们连接在一起。我不确定是否100%了解您的问题,但我认为这将满足您的需要
limitedQuantitiesWithTypeFromApi2$ = this.loadLimitQuantities()
.pipe(
switchMap(
x => forkJoin(x.map(y => this.getType(y.ifsType))),
),
);
ngOnInit() {
forkJoin(this.loadTypes(), this.limitedQuantitiesWithTypeFromApi2$)
.subscribe(([types, lq]) => console.log('Original 1', types, lq));
forkJoin(this.loadTypes(), this.loadLimitQuantities())
.pipe(
map(([types, lq]) => {
return lq.map(x => ({
...x,
type: types.find(y => y.ifsType === x.ifsType)
}))
})
)
.subscribe(x => console.log('Alternate Approach', x));
}
loadTypes() {
return timer(1000).pipe(
map(x => ([
{ ifsType: 1, type: 'vText1'},
{ ifsType: 2, type: 'vText2'}
])),
share()
);
}
loadLimitQuantities() {
return timer(1000).pipe(
map(x => ([
{ifsType: 1, type: null, },
{ifsType: 2, type: null }
])),
share(),
);
}
getType(ifsType: number) {
return timer(1000).pipe(
map(x => ifsType === 1 ? 'vText1' : 'vText2'),
map(x => ({ ifsType, type: x })),
share()
);
}
然而,我认为可以安全地假设您的API2是一个HTTP调用——虽然它可以工作,但我建议您只批量获取所有“类型关联”,这样您就可以创建一个更简单的流
我的意思是,如果loadTypes
已经有了ifsType
到type
的关联,那么你可以只做“方法2”订阅-如果你使用angular,你可以只使用async
管道订阅loadTypes
和loadLimitedQuantilities
,谢谢你的回复,但是在任何时候,数据都不会被推入主题this.limitQuantitiesSubject.next(data)
。另外,我在loadLimitQuantilities()
中有生成错误,我希望将它们都放在同一个函数中。在元素类型观测值解决后,是否需要将数据推送到主题中?是的,因为加载函数(loadObjects()
)只执行一次,结果是推入存储的主题,以便我的组件可以订阅它(private objects subject=new behavior subject([]);public objects$=this.objects subject.asObservable();
)。感谢您的回答,这对我帮助很大,另一方面,数据必须推送到一个主题中,以便我的组件可以订阅它,因此我添加了一个方法来更改存储数据,而不是直接以另一种方法返回它。