您好我正在开发一个应用程序,它将部署在安装了扫描仪设备的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';
基于此扫描目标,我应用过滤器进行不同的调用。我的问题是这个解决方案不起作用?是因为我需要放三个不同的订阅吗?我怎样才能使它工作?
谢谢
如果你想在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
});
你可以试试这个
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);
});