Reputation: 574
Hello I'm developing an app that is gonna be deployed on an android device with a scanner device attached. I have developed the service part that gets the scanned data. My problem now is that I have to differenciate 3 api calls when the device start scanning. I'll explain myself better:
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);
});
}
Inside DestinationService
I have defined this:
scannedDestination: 'Api1' | 'Api2' | 'Api3';
And based on this scannedDestination I apply a filter to make different calls. My problem is that this solution doesn't work? Is it because I need to put three different subscriptions? How can I make it work?
Thank you
Upvotes: 0
Views: 97
Reputation: 8558
You can use switch/case
in switchMap
if you want to do it in 1 subscription:
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;
}
}
});
Edit Note: I added combineLatest
to pass apiCallType
value with the subscription itself to choose which BehaviorSubject
to invoke when subscription generates a value. Therefore, a second switch/case
is added to the subscribe
callback.
combineLatest
should be imported like this: import { combineLatest } from 'rxjs';
Update 2
As you asked in the comments, if you want to call another API (I assume it is an independent API call meaning it has nothing to do with the response) you can use tap
from 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
Upvotes: 1
Reputation: 1793
You can try this
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);
});
Upvotes: 1