Angular 6:如何并行进行一组服务调用,并在所有调用完成后处理数据
我正在使用rxjs 6+开发Angular 6+web应用程序 有一组服务(所有服务都不同,并进行不同的http调用)。 基本上,这些服务用于初始化应用程序 我的要求是并行调用这些服务并等待它们全部完成。完成后,我需要处理收到的回复。 我对此做了很多研究,发现forkJoin和CombineTest可以成为我的朋友。 我通过以下方式实现了相同的功能:Angular 6:如何并行进行一组服务调用,并在所有调用完成后处理数据,angular,rxjs,observable,angular6,rxjs6,Angular,Rxjs,Observable,Angular6,Rxjs6,我正在使用rxjs 6+开发Angular 6+web应用程序 有一组服务(所有服务都不同,并进行不同的http调用)。 基本上,这些服务用于初始化应用程序 我的要求是并行调用这些服务并等待它们全部完成。完成后,我需要处理收到的回复。 我对此做了很多研究,发现forkJoin和CombineTest可以成为我的朋友。 我通过以下方式实现了相同的功能: getInitialData() { this._authService.openCorsConnection().subscribe(re
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', {}))
);
}
x():可观察的{
const xUrl=EnvironmentConfiguration.endPointConfig.xServiceEndpoint;
让serviceMethod:String='x';
让requestObj:any=this.\u utilHelperSvc.getRequestObject(xUrl,{“y”:“”},serviceMethod);
返回此内容。_http.post(requestObj.url,{“pid”:“”},requestObj)
.烟斗(
catchError(this.handleError('x',{}))
);
}
我需要修改服务吗?
我不知道如何解决这个问题
有谁能提出更好的解决方案或不同的方法吗
谢谢 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
将此转换为另一个可观察对象
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
:
所有进程只发出一次,然后完成:例如http Get或Post请求
您希望从源中获取联接输出
实施:
zip(doSthg1(process1$), doSthg2(process2$), doSthg3(process3$))
.subscribe(
([x,y,z]) => {
console.log(`x=${x}, y=${y}, z=${z}`);
});
经过一番搜索,几天前我刚刚完成了这项工作
主要问题是如何调用API列表
如果您从component.ts调用API,则会得到其中的数据。当您通过服务调用API时,您必须存储API调用的引用
我是这样做的
var pendingAPIList : any = [];
您可以在数组中添加API列表,其中ref为observable
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
})
返回新的可观察对象(observer=>{
var obj={
url:url,
param:param,
ref:observer//您是否尝试用CombineTest替换forkJoin?有效吗?@YGLin是的..两者的行为方式相同。即使对服务进行写订阅,forkJoin的回调也不会执行…我注意到您有两级订阅,您确定第一级是openCorsConnection()吗,按预期发射?如果是这样,您可能需要逐个检查这些服务调用,以确保每个服务调用都成功发射。无法为您提供更多帮助,抱歉~如果forkJoin
不发射任何值,则您的一个源观测不发射任何东西或不发射complete@madjaous谢谢…我会试试这个…而且我已经更新了服务正文在我的问题中。你能告诉我是否需要任何修改吗?是的,我需要处理每个服务的数据。我不确定“所有服务发出一次”的意思是,但是是的。所有服务都会返回数据。谢谢兄弟。我实施后会通知你。
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();
}
}