当其他人调用相同的方法时,取消HTTP请求



我在应用程序中使用angular、ngrx和rxjs。当一个效果被调用两次时,第一个效果http请求被取消,只计算第二个。

我想在ngrx范围之外的函数中模拟它。

我有以下方法:

checkMissionPoint(
positions: Array<Cesium.Cartographic>
): Observable<{
valid: boolean;
response: Array<CheckWaypointResponse>;
}> {
return this.store$.pipe(
select(TransactionsStoreSelectors.selectedTransactionId),
take(1),
switchMap((tId) =>
this.httpClient
.post<Array<CheckWaypointResponse>>(
HTTPUtils.getPath(`${environment.FLIGHT_URL}/trajectories/${tId}/checkpoints`),
{positions}
)
.pipe(
switchMap((result) => {
return result;
})
)
)
);
}

我在应用程序的各个地方的应用程序中这样调用这个方法

this.missionHelperService.checkMissionPoint(positions)

现在,我知道了一些取消它的丑陋方法,保持像引用一样,如果再次调用该方法,并且引用仍然存在,则取消订阅。但我想知道是否有一种很好的rxjs方法可以实现这一点。

谢谢。

编辑:我做了一个小堆栈,但你需要在铬控制台中设置慢速3G连接https://angular-xm2ixt.stackblitz.io

你会注意到obs被调用了两次,api将同时启动和应答,我想要的是第二次调用取消第一次调用(并向正在侦听的人发送一个错误,sub 2将失败,正常(

我遇到了一个非常类似的情况,这就是我解决它的方法。

checkMissionPointCalled = new EventEmitter<void>();
checkMissionPoint(
positions: Array<Cesium.Cartographic>
): Observable<{
valid: boolean;
response: Array<CheckWaypointResponse>;
}> {
this.checkMissionPointCalled.emit();
return this.store$.pipe(
select(TransactionsStoreSelectors.selectedTransactionId),
take(1),
switchMap((tId) =>
this.httpClient
.post<Array<CheckWaypointResponse>>(
HTTPUtils.getPath(`${environment.FLIGHT_URL}/trajectories/${tId}/checkpoints`),
{ positions }
)
),
takeUntil(this.checkMissionPointCalled)
);
}

然而,我无法使用

.pipe(
switchMap((result) => {
return result;
})
)

httpClient.post调用之后,我认为这可能是一个错误。所以,我没有把它包括在我的答案中。

您可能还想在ngOnDestroy方法中关闭checkMissionPointCalled

现在的问题是,checkMissionPoint()方法为每个调用者返回一个全新的可观察对象。

我认为,如果你有一个私人可观察对象,并将该可观察对象返回给所有呼叫者,你就可以实现你想要做的事情。这个可观察到的将使用switchMap()来实现您正在寻找的取消行为。

private positions$ = new Subject();
private uri$ = this.store$.pipe(
select(TransactionsStoreSelectors.selectedTransactionId),
map(tId => HTTPUtils.getPath(`${environment.FLIGHT_URL}/trajectories/${tId}/checkpoints`)
);
private checkMissionPoint$ = combineLatest([this.uri$, this.positions$]).pipe(
switchMap(([uri, positions]) => this.httpClient.post<CheckWaypointResponse[]>(uri, {positions}))
);
checkMissionPoint(
positions: Array<Cesium.Cartographic>
): Observable<{
valid: boolean;
response: Array<CheckWaypointResponse>;
}> {
this.positions.next(positions);
return this.checkMissionPoint$.pipe(
take(1)
);
}

根据您的用例,让方法返回void并将公共可观察对象公开:可能会更干净

private positions$ = new Subject();
private uri$ = this.store$.pipe(
select(TransactionsStoreSelectors.selectedTransactionId),
map(tId => HTTPUtils.getPath(`${environment.FLIGHT_URL}/trajectories/${tId}/checkpoints`)
);
public missionPoint$ = combineLatest([this.uri$, this.positions$]).pipe(
switchMap(([uri, positions]) => this.httpClient.post<CheckWaypointResponse[]>(uri, {positions}))
);
setPosition(
positions: Array<Cesium.Cartographic>
): Observable<{
valid: boolean;
response: Array<CheckWaypointResponse>;
}> {
this.positions.next(positions);
}

最新更新