【问题标题】:Cancel an HTTP request when someone else call same method当其他人调用相同的方法时取消 HTTP 请求
【发布时间】:2020-12-29 03:25:03
【问题描述】:

我在我的应用程序中使用 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 方法来实现这一点。

谢谢。

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

你会注意到 obs 被调用了两次,api 会触发和应答,我想要的是第二次调用取消第一次(并向正在监听的人发送错误,sub 2 将正常运行)

【问题讨论】:

  • 我对你的要求有点困惑。您是说您发布的代码有效吗?你只想要没有 rxjs 的相同功能?
  • 能否提供一个 stackblitz 演示?这会很有帮助。

标签: angular rxjs


【解决方案1】:

我也遇到过类似的情况,我就是这样解决的。

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

【讨论】:

  • 谢谢,我会检查一下,使用它是因为在我的真实应用程序中我在那里做了一些操作,所以我包含了一个简单的函数来表明我在那里做某事。
  • 您的解决方案确实有效,我认为这不是最好的 rxjs,但它确实可以解决问题,谢谢。而且由于这里没有其他人回应...
【解决方案2】:

您现在遇到的问题是,checkMissionPoint() 方法为每个调用者返回一个全新的 observable。

如果你有一个私有的 observable 并将相同的 observable 返回给所有调用者,我认为你可以实现你想要做的事情。这个 observable 将使用 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);
}

【讨论】:

  • 您的回答包含错误和拼写错误,但它解决了问题。谢谢。
  • 我尝试了第一个解决方案,因为它更适合我的用例,它确实取消了,但它使用最新参数创建了更多 api 调用。就像我调用 1 次,取消,下一次调用将创建 2 个具有相同参数的 api 调用,然后取消,3 将进行 3 等等......我认为取消调用应该返回错误或其他东西。
  • switchMap 将在有新的 API 调用时取消当前正在进行的 API 调用。exhaustMap 将忽略新的请求,直到当前的请求完成。
  • @MrkSef switchMap 是我想要的,答案是什么,问题是它确实取消了 API,但它调用了多个而不是单个。但是如果答案没有问题,那么它可能在我的代码中?
猜你喜欢
  • 2011-03-05
  • 2019-09-12
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多