Angular 2 多次订阅

Angular 2 multiple subscription

您好,我正在开发一个应用程序,该应用程序将部署在连接了扫描仪设备的 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';

基于这个 scannedDestination,我应用了一个过滤器来进行不同的调用。 我的问题是这个解决方案不起作用?是因为我需要放三个不同的订阅吗? 我怎样才能让它发挥作用?

谢谢

你可以试试这个

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

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

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

        });

do/tap : https://www.learnrxjs.io/operators/utility/do.html