Angular 6:如何并行进行一组服务调用,并在所有调用完成后处理数据

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

我正在使用rxjs 6+开发Angular 6+web应用程序

有一组服务(所有服务都不同,并进行不同的http调用)。 基本上,这些服务用于初始化应用程序

我的要求是并行调用这些服务并等待它们全部完成。完成后,我需要处理收到的回复。 我对此做了很多研究,发现forkJoin和CombineTest可以成为我的朋友。 我通过以下方式实现了相同的功能:

 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();   
         }
    }