避免陷阱

本篇章将介绍一些在Angular应用中的由于使用不当引起不必要的麻烦。

一、Http 需要取消订阅吗?

首先,先来看一下:

const sub = Observable.fromEvent(node, 'input')
  .map((event: any) => event.target.value)
  .filter(value => value.length >= 2)
  .subscribe(value => {
      console.log(value);
  });

Observable.fromEvent 内部实际是利用 addEventListener 对DOM元素添加一个事件监听;而对事件的移除变得非常重要,这是因为对但一个事件被记录以后,取触发是用户在决定什么时候录入以后会产生触发。因此,这会让我们产生另一个问题,我们是无法得知用户是否已经不打算录入,除非用户关掉浏览器。所以,移除事件会变得非常重要,因为如果不移除事件所关联的方法会持续一直被占用,从而会形成内存泄露危险,我们把这种行为称为:无限值

回过头来看示例中 Observable.fromEvent,如果调用 sub.unsubscribe() 会执行 removeEventListener 动作。

接着,再来看一个 Http 示例。

const sub = this.http
  .get('/my')
  .subscribe(value => {
      console.log(value);
  });

对于 Http 其内部实际是产生一个 xhr 请求对象,大概如下:

let xhr = new XMLHttpRequest();
xhr.addEventListener('load', () => {
  if (response.ok) {
    responseObserver.next(response);
    responseObserver.complete();
  } else {
    responseObserver.error(response);
  }
}));
xhr.send();

当请求返回成功后直接调用观察者的 nextcomplete。虽然这里也有 addEventListener 动作,但是相比较DOM事件而已,我们不必担心,因为当调用 complete 会表示其已经结束;同时,对于这里的事件而言已经不会再被调用,从而JavaScript会在适当的时候自动销毁,我们把这种行为称为:有限值

因此:对于无限值务必要手动取消订阅,反之可以不需要。

二、不要嵌套 Observable

很多情况下,一个数据请求可以需要依赖于另一个请求时,可能会这么写:

this.userSrv.get().subscribe(user => {
  this.getList(user.id).subscribe(list => {
    console.log(user, list);
  });
});

我们又回到类似回调地狱的那种状态。而其实 Observable 只需要使用 flatMap 很容易避开这种状态,而且非常优雅。

this.userSrv.get()
    .do(user => {
      this.user = user;
    })
    .flatMap(user => this.getList(user.id))
    .subscribe(list => {
      console.log(user, list);
    });

results matching ""

    No results matching ""