Angular 2多次订阅

问题描述 投票:0回答:2

您好我正在开发一个应用程序,它将部署在安装了扫描仪设备的Android设备上。我开发了获取扫描数据的服务部分。我现在的问题是,当设备开始扫描时,我必须区分3个api呼叫。我会更好地解释自己:

      scannedResult$ = new BehaviorSubject<Api1Response>(null);
      scannedResultApi2$ = new BehaviorSubject<Api2Response>(null);
      scannedResultApi3$ = new BehaviorSubject<Api2Response>(null);

      constructor(
        private scanData: ScanDataService,
        private api: ApiService,
        private scannedDestination: DestinationService
      ) {
        super();
        const scannedResult$ = this.scanData.scanResult$
        .pipe(
          filter(_ => this.scannedDestination.scanDestination === 'Api1'),
          tap(_ => (this.scanning = false)),
          switchMap(scanned=>
            this.api.callApi(Api1Query, {
              DataBar: scanned.DataBar
            })
          )
        )
      .pipe(
      filter(_ => this.scannedDestination.scanDestination === 'Api2'),
      tap(_ => (this.scanning = false)),
      switchMap(scanned =>
        this.api.callApi(Api2Command, {
          DataBar: scanned.DataBar
        })
      )
    )
    .pipe(
      filter(_ => this.scannedDestination.scanDestination === 'Api3'),
      tap(_ => (this.scanning = false)),
      switchMap(scanned =>
        this.api.callApi(Api3Command, {
          DataBar: scanned.DataBar
        })
      )
    )
    .subscribe(result => {
      this.scannedResult$.next(result);
    });
}

DestinationService里面我定义了这个:

scannedDestination: 'Api1' | 'Api2' | 'Api3';

基于此扫描目标,我应用过滤器进行不同的调用。我的问题是这个解决方案不起作用?是因为我需要放三个不同的订阅吗?我怎样才能使它工作?

谢谢

angular api angular2-services
2个回答
1
投票

如果你想在1个订阅中使用switch/case,你可以使用switchMap

const scannedResult$ = this.scanData.scanResult$
        .pipe(
          tap(_ => (this.scanning = false)),
          switchMap(scanned=> {
            let apiCallType = '';
            switch(this.scannedDestination.scanDestination){
              case 'Api1':{
               apiCallType = Api1Query;
               break;
              },
              case 'Api2':{
               apiCallType = Api2Command;
               break;
              },
              case 'Api3':{
               apiCallType = Api3Command;
               break;
              }
            }
            return combineLatest(
                     this.api.callApi(apiCallType, {
                       DataBar: scanned.DataBar
                     }),
                     of(this.scannedDestination.scanDestination)
                   )
          })
        )
.subscribe(([result, apiType]) => {

       switch(apiType){
              case 'Api1':{
               this.scannedResult$.next(result);
               break;
              },
              case 'Api2':{
               this.scannedResultApi2$.next(result);
               break;
              },
              case 'Api3':{
               this.scannedResultApi3$.next(result);
               break;
              }
            }

});

编辑注意:我添加了combineLatest以通过订阅本身传递apiCallType值,以选择在订阅生成值时调用哪个BehaviorSubject。因此,第二个switch/case被添加到subscribe回调中。

combineLatest应该像这样进口:import { combineLatest } from 'rxjs';

更新2

正如您在评论中提到的,如果您想调用另一个API(我假设它是一个独立的API调用,这意味着它与响应无关),您可以使用tap中的rxjs

       const scannedResult$ = this.scanData.scanResult$
        .pipe(
          tap(_ => (this.scanning = false)),
          switchMap(scanned=> {
            let apiCallType = '';

            let is2or3 = false; // flag to check if Api2Command or Api3Command

            switch(this.scannedDestination.scanDestination){
              case 'Api1':{
               apiCallType = Api1Query;
               break;
              },
              case 'Api2':{
               apiCallType = Api2Command;
               is2or3 = true;
               break;
              },
              case 'Api3':{
               apiCallType = Api3Command;
               is2or3 = true;
               break;
              }
            }


             let apiToCall = this.api.callApi(apiCallType, {
                       DataBar: scanned.DataBar
                     });

            if(is2or3){
                apiToCall = apiToCall.pipe(
                    tap(() => {
                         // do the other API call here.
                         // this.anotherApiCall();
                    })
                )
            }

            return combineLatest(
                     apiToCall,
                     of(this.scannedDestination.scanDestination)
                   )
          })
        )
       .subscribe(([result, apiType]) => {

           // same as above

        });

做/点击:https://www.learnrxjs.io/operators/utility/do.html


1
投票

你可以试试这个

 const scannedResult$ = this.scanData.scanResult$
        .pipe(
          filter(_ => ),
          tap(_ => (this.scanning = false)),
          switchMap(scanned=>
            this.api.callApi(this.scannedDestination.scanDestination === 'Api1'? Api1Query: (this.scannedDestination.scanDestination === 'Api2'? Api2Command : Api3Command), {
              DataBar: scanned.DataBar
            })
          ).subscribe(result => {
      this.scannedResult$.next(result);
    });
© www.soinside.com 2019 - 2024. All rights reserved.