RxJs

时间:2018-01-17 23:08:43

标签: angular exception-handling rxjs

我很难理解RxJS以及如何处理错误。我正在使用Angular(4+)并且为了简单的HTTP请求切换到RxJS,我发现自己不得不用一些看似微不足道的东西来努力。

这是我非常人为的代码:

import { Component, OnInit } from '@angular/core';

import 'rxjs/add/observable/from';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/observable/throw';

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/switchMap';

import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
    title = 'app';
    index = 0;
    sub1: Subscription;
    fail = false;

    // the event generated by the user (click)
    eventA = new BehaviorSubject<number>(0);

    // another event, downstream from eventA
    eventB = this.eventA.mergeMap(x => this.fetchData(x));

    constructor() { }

    ngOnInit(): void {
        this.sub1 = this.eventB.catch(err => {
            console.log(`error was caught!`);
            return this.eventB;
        }).subscribe(x => {
            this.title = x.toString();
        });
    }

    doIt() {
        this.eventA.next(Date.now());
    }

    fetchData(input: number) {
        if (this.fail) {
            return Observable.throw(new Error(`I failed!`));
        }
        return Observable.of(input);
    }
}

和html:

<input type="checkbox" [checked]="fail" (change)="fail = !fail" >Fail<br>
<button (click)="doIt()">doit()</button><br>
{{title}}

这是演示

demo GIF

如您所见,一旦失败,管道就不再执行了。我可以确认eventA仍然是好的,eventB也是如此。但是,似乎sub1已取消订阅。

最后一部分是我不明白的。我明确地返回eventB以便它可以继续...或者我是否完全错了?

我的用例是:

  • 我有一个业务事件(eventA),强制在应用程序中刷新数据。
  • 我不想强迫应用程序中的所有组件监听该事件,然后请求他们的新数据,而是希望利用Rx的强大功能让数据流通过应用程序。 / LI>
  • 因此,我的组件订阅各种下游事件
  • 我遇到的问题是,与任何数据调用一样,它可能有错误。我希望每个组件都能自行处理错误。
  • 下游事件可能会为那些不良数据通话产生错误,因此如何让订阅者知道错误而不会删除数据流?

1 个答案:

答案 0 :(得分:2)

在触发器observable上使用.switchMap()以获得每次单击的新提取,并在switchMap内而不是在eventB之后捕获。

switchMap每次都会有效地提供一个新的内部订阅,所以如果旧版本因错误而关闭,则下次点击它会再次启动它。

唯一可能的缺点是,在获取完成之前发生另一次点击时,第一次点击的提取会被丢弃。

eventB = this.eventA.switchMap(x => {
  return this.fetchData(x)
    .catch(err => {
      console.log(`error was caught!`, err);
      return Observable.empty();
    })
});

...

ngOnInit(): void {
  this.sub1 = this.eventB
    .subscribe(x => {
        this.title = x.toString();
      }
    );

这是我测试过的StackBlitz