【问题标题】:RxJS: Observable.never() keeps like subscriptionRxJS:Observable.never() 保持订阅状态
【发布时间】:2019-09-26 05:30:18
【问题描述】:

我正在使用 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

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

有什么想法吗?

真实案例

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();

【问题讨论】:

  • 你为什么deleting 并转发同样的问题?你觉得这会给你答案吗??
  • the subscription terminates 是什么意思?
  • 订阅应该继续处理2值而不是停止...

标签: angular typescript rxjs


【解决方案1】:

你得到输出

1 
error catched

因为第一个值在tap 中引发错误,该错误通过停止序列的onError 通道传播。使用catch,您会发现此错误并继续执行下一个序列 (never),但第一个序列 (of(1,2)) 仍会停止。所以在1 抛出错误之后2 永远不会被tap 处理。

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

【讨论】:

    【解决方案2】:

    是的,@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 属性,即使在这种情况下您希望继续处理流。如果这是真的那么你可以在do()下添加一个简单的trycatch

      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

    【讨论】:

    • 我在帖子中添加了我的真实案例。如您所见,它尝试向服务发出请求。你能看一下吗?我希望不再需要代码...
    • @Jordi 是什么导致了异常? page => this.loadedPage(page)do 下?
    猜你喜欢
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    相关资源
    最近更新 更多