RxJS:Observable.never()保持订阅状态

时间:2019-05-08 13:02:26

标签: angular typescript rxjs

我正在使用rxjs 5.5.6。

我已创建此代码以显示其行为:

Observable.of(1, 2)
    .do(a => {
        console.log(a);
        let d:string = null;
        let r = d.length;  // it raises an null exception
    })
    .catch(() => {
        console.log("error catched");  //exception is capture here
        return Observable.never();
    })
    .subscribe();

我期望输出为:

1
error catched
2
error catched

但是,输出为:

1
error catched

这意味着,尽管Observable.never()方法链上返回了.catch(...),订阅还是终止了。

有什么想法吗?

真实案例

this.subs = Observable
    .merge(this.$searchQuery, this.$lazyQuery)
    .do(() => this.loadingPage())
    .map(filter => this.buildURL(user, app, filter))
    .switchMap(url => this.service.getItemsFromService(url))
    .map(response => this.buildPage(response))
    .do(page => this.loadedPage(page))
    .catch(() => {
        this.loadedPage(pojo.Page.EMPTY);
        return Observable.never();
    })
    .takeUntil(this.$unsubscribe)
    .subscribe();

2 个答案:

答案 0 :(得分:1)

您将获得输出

1 
error catched

因为第一个值在tap中引发错误,该错误会通过onError通道传播,从而终止序列。使用catch时,您会捕获到此错误并继续执行下一个序列(never),但是第一个序列(of(1,2))仍被暂停。因此,1引发错误后,2永远不会处理tap

never中返回catch后,不会发出任何值,并且Observable永远不会完成。如果在subscribe内为nexterrorcomplete回调添加日志,您将发现它们从未执行过。

答案 1 :(得分:1)

是的,@ frido的所有解释都是正确的。有了这个答案,我想补充:

如果要捕获任何特定的Observable本身发生的任何错误(例如HTTP请求),则需要在该特定的错误Observable中对其进行处理。

  let correct = Observable.of("correct")
  let inCorrect = Observable.throw('inCorect')

  let obs = [inCorrect, correct];
  let handledObs = obs.map(eachObs => {
    return eachObs.catch((e) => {
      console.log("Individual handler, Good Catch!");
      return Observable.of("I am tampered");
    })
  })

  forkJoin(...handledObs)
  .do(a => {
      console.log(a);
  })
  .catch(() => {
      console.log("error catched");
      return Observable.never();
  })
  .subscribe(data => {
    console.log(`data`, data)
  },(e) => {
      console.log(`error`, e)
  });

}

在此处查看示例:https://stackblitz.com/edit/angular-7mmhn7?file=src/app/app.component.ts


编辑

但是,当我查看您的代码时,在我看来您正在尝试记录某些内容,并且返回的数据可能没有length属性,即使在这种情况下,您也想继续使用流。如果是这样,则可以在try

下添加一个简单的catch do()
  from([1, 2])
  .do(a => {
      try {
        console.log(a);
        let d:string = null;
        let r = d.length;
      } catch(e) {
        console.log(`catched under do`, e)
      }
  })
  .catch(() => {
      console.log("error catched");
      return Observable.of('catched');
  })
  .subscribe(data => {
    console.log(`data`, data)
  },(e) => {
      console.log(`error`, e)
  });

这里是一个示例:https://stackblitz.com/edit/angular-bcrava?file=src/app/app.component.ts