【问题标题】:Catch error in combined pipe of pipeable rxjs operators在可管道 rxjs 运算符的组合管道中捕获错误
【发布时间】:2018-04-28 21:08:53
【问题描述】:

我们刚刚将我们的一个应用程序升级到 Angular 5,并开始转换为 rxjs v5.5 中引入的lettable operators

因此,我们使用 .pipe() 运算符将可观察管道重写为新语法。

我们之前的代码看起来像这样,在.switchMap() 内部有一个.catch(),以便在抛出错误时不会中断效果的运行。

@Effect()
loadData$ = this.actions$
.ofType(LOAD_DATA)
.map((action: LoadData) => action.payload)
.withLatestFrom(this.store.select(getCultureCode))
.switchMap(([payload, cultureCode]) => this.dataService.loadData(payload, cultureCode)
  .map(result => {
    if (!result) {
      return new LoadDataFailed('Could not fetch data!');
    } else {
      return new LoadDataSuccessful(result);
    }
  })
  .catch((err, caught) => {
    return Observable.empty();
  });
  );

如果在调用dataService 时出现错误,它将被捕获并处理(此处简化了错误处理)。

有了.pipe() 的新语法和使用,我们现在有了这个

@Effect()
loadData$ = this.actions$
.ofType(LOAD_DATA)
.pipe(
  map((action: LoadData) => action.payload),
  withLatestFrom(this.store.select(getCultureCode)),
  switchMap(([payload, cultureCode]) => this.dataService.loadData(payload, cultureCode)),
  map(result => {
    if (!result) {
      return new LoadDataFailed('Could not fetch data!');
    } else {
      return new LoadDataSuccessful(result);
    }
  })
  );

如何使用新语法以类似的方式捕获可观察管道中抛出的任何错误?

【问题讨论】:

  • 重构后,您将map 移出switchMap 投影,因此任何错误都会关闭外部流。类似:switchMap(([payload, cultureCode]) => this.dataService.loadData(payload, cultureCode).pipe(map..., catch...)) 应该可以完成这项工作。
  • 效果很好@arturgrzesiak!将其发布为答案,我会接受! :)

标签: angular rxjs ngrx-store ngrx-effects angular5


【解决方案1】:

重构后,您将map 移出switchMap 投影,因此任何错误都会关闭外部流。为了使两个流保持相同,您需要在投影本身中使用pipe,如下所示:

import { empty } from 'rxjs;

// ...

@Effect()
loadData$ = this.actions$
.ofType(LOAD_DATA)
.pipe(
  map((action: LoadData) => action.payload),
  withLatestFrom(this.store.select(getCultureCode)),
  switchMap(([payload, cultureCode]) =>
    this.dataService.loadData(payload, cultureCode)
      .pipe(
         map(result => {
           if (!result) {
             return new LoadDataFailed('Could not fetch data!');
           } else {
             return new LoadDataSuccessful(result);
           }
          }),
         catchError((err, caught) => {
           return empty;
         })
      )
  )
);

【讨论】:

  • 这完全符合我的预期,尽管catch 已重命名为catchError!谢谢!
  • 我必须这样做:import { empty } from 'rxjs;,然后是 rjxs v6 中的empty()
  • 仅供参考,empty() 已被弃用,取而代之的是 EMPTY 常量: import {EMPTY} from "rxjs/internal/observable/empty"
  • @jk。不确定 - 你能粘贴一个发布说明的链接吗?我在6.3.3,有empty。此外,直接从rxjs/internal 导入对我来说似乎有点奇怪。
  • @artur grzesiak 链接到我所看到的:github.com/ReactiveX/rxjs/blob/master/src/internal/observable/… 看起来确实很奇怪,但它是 intellij 中唯一没有弃用的。我在 rxjs-compat@6.3.2 和 rxjs@6.2.0。不确定我是否需要这两个..
【解决方案2】:

你也可以这样做。

import { of } from 'rxjs';

@Effect()
loadData$ = this.actions$
.ofType(LOAD_DATA)
.pipe(
  map((action: LoadData) => action.payload),
  withLatestFrom(this.store.select(getCultureCode)),
  switchMap(([payload, cultureCode]) =>
    this.dataService.loadData(payload, cultureCode)
      .pipe(
         map(result => {
           if (!result) {
             return new LoadDataFailed('Could not fetch data!');
           } else {
             return new LoadDataSuccessful(result);
           }
          }),
         catchError(err => of('error', err))
      )
  )
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多