rxjs condition inside flatmap

2019-07-22 20:46发布

I want to have a condition inside flatMap that checks what was returned by first observable. If condition is not met I would like to break and navigate to different page.

this.service.getData(id)
  .flatMap((data) => {
    if (!data) {
      return Observable.throw(new NoDataFoundError());
    }
    return Observable.forkJoin(
      this.service.getData2(id2),
      this.service.getData3(id3),
    );
  })
  .subscribe(
    ([data2, data3]) => {
      this.data2= data2;
      this.data3= data3;
    },
    (err) => {
      if (err instanceof NoDataFoundError) {
        this.router.navigate(...);
      }
    }
  );   

Currently I'm throwing specific error and catching it however I don't like this solution as it's not the only piece of code that could throw an error and the if is not scaling.

I thought about filter or takeWhile operators but I won't be able to execute the redirect.

I also thought about returning Observable.of instead of throwing (in line 4) but then I would have to do the if in subscribe which also smells.

标签: angular rxjs
1条回答
疯言疯语
2楼-- · 2019-07-22 21:38

You can execute this.router.navigate and return Observable.empty() inside .flatMap. This way you will have a single if statement.

.flatMap(data => {
  if (!data) {
    this.router.navigate(...);
    return Observable.empty();
  }
  return (...);
})

But usually Observables should be lazy and pure(free of side effects) this will make them predictable and easy to compose. Side effects should be performed only by subscriber.

In your specific case, it seems like the proper solution would be to put this logic in the route guard, like described here - https://stackoverflow.com/a/39162538/3772379

查看更多
登录 后发表回答