我正在使用rxjs 6+开发Angular 6+ Web应用程序。
有一组服务(所有服务都不同,并且会进行不同的http调用)。 基本上,这些服务用于初始化应用程序。
我的要求是并行调用这些服务,并等到它们全部完成为止。完成后,我需要处理收到的回复。 我对此进行了很多研究,发现forkJoin和CombineLatest可以成为我的朋友。 而且我已经通过以下方式实现了相同的方法:
getInitialData() {
this._authService.openCorsConnection().subscribe(res => {
forkJoin(
this._authService.x(),
this._tService.getSystemDate(),
this._tService.getTemp(),
this._tService.getSettings()
).pipe(
catchError( err => {
console.log('gor error',err);
if (err.status == 401) {
// this._router.navigateByUrl('/unauthorize');
return EMPTY;
} else {
return throwError(err);
}
}),
map(([x,y,z,p])=>{
console.log('sucesss',{x,y,z,p});
return {x,y,z,p}
}),
finalize(()=>{
console.log('Executing Finally');
processData();
})
);
});
}
但是这些没有执行。以下是服务:
x(): Observable<any> {
const xUrl = EnvironmentConfiguration.endPointConfig.xServiceEndpoint;
let serviceMethod: String = 'x';
let requestObj: any = this._utilHelperSvc.getRequestObject(xUrl , { "y": "" }, serviceMethod);
return this._http.post<any>(requestObj.url,{ "pid": "" } , requestObj)
.pipe(
catchError(this.handleError('x', {}))
);
}
我需要修改服务吗? 我不知道如何解决这个问题。
有人可以为此建议一些更好的解决方案或其他方法吗?
谢谢。
答案 0 :(得分:2)
TL; DR
演示:
说明
您无需等待forkJoin
处理响应,反之亦然。相反,准备所有需要完成的工作,然后等待完成。
这是我的意思:
let process1$ = timer(1000);
let process2$ = timer(2000);
let process3$ = timer(3000);
const doSthg1 = pipe(
tap(() => console.log('Process 1 has finished')),
map(() => 'Process 1 has finished')
)
const doSthg2 = pipe(
tap(() => console.log('Process 2 has finished')),
map(() => 'Process 2 has finished')
)
const doSthg3 = pipe(
tap(() => console.log('Process 3 has finished')),
map(() => 'Process 3 has finished')
)
forkJoin(doSthg1(process1$), doSthg2(process2$), doSthg3(process3$)).subscribe(() => {
console.log('Now I am complete');
});
只要您的进程未链接,即一个输入不依赖于另一个输出,此方法就起作用。
我的代码为什么不起作用?
因为您实际上没有订阅forkJoin
。
解决方案:例如,您可以使用concatMap
将this._authService.openCorsConnection()
转换为另一个Observable:
getInitialData(){
this._authService.openCorsConnection().pipe(
concatMap(() => forkJoin(this._authService.x(),
this._tService.getSystemDate(),
this._tService.getTemp(),
this._tService.getSettings()
)),
catchError(err => {
console.log('gor error', err);
if (err.status == 401) {
return EMPTY;
} else {
return throwError(err);
}
}),
).subscribe(() => processData());
}
zip
在以下情况下,您可以使用zip
代替forkJoin
:
实现:
zip(doSthg1(process1$), doSthg2(process2$), doSthg3(process3$))
.subscribe(
([x,y,z]) => {
console.log(`x=${x}, y=${y}, z=${z}`);
});
答案 1 :(得分:0)
几天前,我经过大量搜索。
最主要的是如何调用API列表。
如果您从 component.ts 调用API,那么您将获得其中的数据。不同之处在于,当您通过服务调用API时,必须存储API调用的引用。
我已经通过这种方式完成了...
var pendingAPIList : any = [];
您可以将api列表添加到具有可观察参考的数组中。
return new Observable(observer => {
var obj = {
url:url,
param:param,
ref : observer // <-- Hear is the main trick
}
this.pendingAPIList.push(obj); // Add multiple API in array
})
添加了所有API后,然后调用...
Observable.forkJoin(this.pendingAPIList).subscribe(response){
// You will get data in array
// Now return all API res in their subscribers at .ts file...
for(let i = 0 ; i < this.pendingAPIList.lengh ; i++ ){
this.pendingAPIList[i].ref.next(response[i]);
this.pendingAPIList[i].ref.complete();
}
}
这对我来说很好...:)