RxJs Observable:如何拦截寒冷的可观察物?

时间:2016-11-17 11:55:07

标签: angular rxjs

我正在构建一个Angular 2应用程序 - 我想要的一件事是一个加载指示器组件,每次运行http请求时都是可见的。

我构建了自己的可注入RestService,它包装了Http服务。

我的RestService公开类似" get()"等方法。和" post()",内部调用Http.get()或Http.post()。现在的计划是拦截调用我自己的一组Observables(实际上是主题),我打电话给#34; requestStarted"和" requestFinished"。

我尝试了以下内容:

public get(url: string): Observable<any> {
  this.requestStarted.next();
  let request = this.get(url)
                    .map(r => r.json())
                    .catch(this.handleError);
  request.subscribe(() => this.requestFinished.next());
  return request;
}

这确实产生了意想不到的结果:突然每个请求都发出两次......我相信这与Http.get()返回一个冷可观察的事实有关。现在使用&#34; subscribe()&#34;两次,调用两次。

为了规避这种行为,我最终做了以下事情:

private intercept(observable: Observable<any>): Observable<any> {
  this.requestStarted.next();
  observable.map(r => {
    this.requestFinished.next(); // <-- USING MAP TO INTERCEPT?
    return r;
  });
  return observable;
}

public get(url: string): Observable<any> {
  let request = this.get(url)
                    .map(r => return r.json())
                    .catch(this.handleError);

  return this.intercept(request);
}

效果很好......但使用&#34; map()&#34;感觉很奇怪。没有实际映射任何东西......对于这种事情,是否有更好的替代算子?

1 个答案:

答案 0 :(得分:2)

使用map可以解决问题,但是有更好的解决方案。让我们说你的通话失败,地图永远不会到达,你永远不会知道你的通话失败,导致一个旋转器继续前进。

你能做的最好的事情就是用最后的替换map函数。这看起来像这样:

public get(url: string): Observable<any> {
  let request = this.get(url)
                .catch(this.handleError)
                .finally(() => this.requestFinished.next());

  return this.intercept(request);
}

始终执行finally,并提供将执行您期望的所有操作的行为。