switchMap 到 keep/cancel 请求 angular http 客户端

switchMap to keep/cancel request with angular http client

我有一些类似于

的ngrx效果
effect1 = this.actions$.pipe(
 ofType('x'), 
 switchMap(data => this.httpClient.post(data)), 
 map(result => new mappedAction(result))
);

对于effect1,当收到新的trigger时,我想忘记并取消之前的请求,取消吧。我读了一些关于它的内容,似乎这就是 httpClient 请求上的 switchMap 所做的事情。

另一个效果2,我们假设,当接收到一个新的触发器时,我不关心上一个请求的结果,但我关心请求是否完成。我应该用什么代替 switchMap?

在那种情况下你应该使用 mergeMap:

effect2 = this.actions$.pipe(
 ofType('x'),
 // inner subscription is not completed on source emition (many subscriptions allowed)
 // but the order in which they complete is not mantained
 mergeMap(data => this.httpClient.post(data)), 
 map(result => new mappedAction(result))
);

如果在您的情况下,顺序很重要,您应该使用 concatMap

注意使用 switchMap 进行服务器端变更。实际上,由于 post 请求,您似乎正在对某些资源进行服务器端变更。您需要确保即使请求在客户端被取消,它仍然由后端处理。

在我看来,对于 effect2,您有 2 个选择。

ConcatMap

ConcatMap 将触发器作为输入参数并将执行您的 http 请求。如果在 http 请求仍在进行时有新触发器,则此触发器将被缓冲,直到内部可观察对象 (http) 完成。根据您的情况,这可能会导致内存溢出。例如,请求需要 10 秒才能完成,但此效果每 100 毫秒触发一次。所有这些触发器都将被缓存并顺序执行。

MergeMap

MergeMap 未缓存触发器。它只是在触发动作后立即订阅内部可观察对象。但是内部可观察对象可能需要不同的时间,例如第一个 http 请求需要 20 秒,第二个 http 请求只需要 1 秒。在这种情况下,第二个 http 请求的操作员链中的进一步步骤将在第一个 http 请求完成之前执行。如果执行顺序对您很重要,这可能是个问题。

请注意,所有这些运算符都会发出 http 响应作为结果。如果您想在 http 请求完成时转发触发值,您可能会使用类似的东西

this.action().pipe(
   concatMap(x => 
       forkJoin([of(x), this.http(...)]).pipe(
           map(([x]) => x)
       )
    )
 );

抱歉缩进不好,我希望它有用,它实际上没有测试和写在我的 phone 上。当代码片段有任何问题时,请告诉我,我可以稍后改进它们。

您可以实现一个自定义运算符,其工作方式与 mergeMap 类似,但仅发出您映射到的最后一个 Observable 的项目。

function mergeMapLast<T, R>(next: ((data: T) => Observable<R>)): OperatorFunction<T, R> {
  return (source: Observable<T>) => defer(() => {
    let curr = 0;
    return source.pipe(
      mergeMap((data, index) => {
        curr = index;
        return next(data).pipe(filter(_ => index === curr));
      })
    );
  });
}

用法

effect2 = this.actions$.pipe(
 ofType('x'), 
 mergeMapLast(data => this.httpClient.post(data)), 
 map(result => new mappedAction(result))
);

https://stackblitz.com/edit/rxjs-vu2gfp