首页 > 解决方案 > RxJS 6 - Angular 6 - 如果触发了新请求,则正确取消当前的 http 请求

问题描述

所以我知道这是完全可能的,但我从来没有使用过 RxJs,只是简单的 http 获取和订阅。我有一个正在监听 WebSocket 事件的服务,当 1 个这样的事件触发时,我调用 Api 来加载一些数据。如果该 websocket 事件在 1 个 api 已经在传输中时触发,我想取消它,然后重新启动一个新的 api 调用。我不确定我是否正确使用 SwitchMap,并且我不知道如何将 Pipe 与 RxJs 6 一起使用。

这是 SwitchMap 和管道的正确用法来获取我的数据吗?在触发大量事件时似乎工作正常,但在最后一个事件触发后似乎有很长的延迟,但这可能是服务器延迟,因为我的 api 服务器也是我的 websocket 服务器。

我的组件:

clients: Client[] = [];

  constructor(public statsApi: StatisticsService)
  {
    this.statsApi.OnClientUpdate.pipe(switchMap(x => { return this.statsApi.GetClients() })).subscribe(x =>
    {
      console.log(x);
      this.LoadClients(x);
    });
  }

  private LoadClients(clients:Client[] = null): void
  { 
    if (clients != null)
    { 
      this.clients = clients;
    } else
    { 
      this.statsApi.GetClients().subscribe(data =>
      {
        this.clients = data;
      });
    }
  }

  ngOnInit() 
  {
    this.LoadClients();
  }

服务内的 GetClients:

public GetClients(): Observable<Client[]>
  { 
    return this.http.get<Client[]>('http://localhost:5000/api/client');
  }

OnClientUpdate returns an Observable<number>

标签: angularrxjs

解决方案


您的代码描述了每次您的OnClientUpdateobservable 产生时发送 http 请求的过程。每个 yield 最终都会选择一个表示 http 请求的 observable。switchMap将订阅该 http 请求 observable 并处理它对任何先前的 http 请求 observable 的订阅。如果该 observable 的订阅正确实现了对 http 请求的处理,switchMap则将按预期工作。

但是,根据产生的频率,您OnClientUpdate 可能需要添加一个debounce操作,从而防止快速触发 http 请求和取消。

示例 - don't spam, cancel all but the latest request, and yield each latest result

var latestHttpRequestResult =
    trigger
        .pipe(debounce(200))
        .pipe(switchMap(sendHttpRequestAsObservable));

推荐阅读