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