您好,我正在开发一个应用程序,该应用程序将被部署在带有扫描仪设备的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';
并基于此scanDestination,我应用了一个过滤器来进行不同的调用。 我的问题是此解决方案不起作用?是因为我需要放置三个不同的订阅吗? 我该如何运作?
谢谢
答案 0 :(得分: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);
});
答案 1 :(得分: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';
应该这样导入:tap
更新2
正如您在评论中所问的那样,如果您要调用另一个API(我假设它是一个独立的API调用,这意味着它与响应无关),则可以使用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
});
display: flex;