如何使用 catchError() 并且仍然返回带有 rxJs 6.0 的类型化 Observable?
Posted
技术标签:
【中文标题】如何使用 catchError() 并且仍然返回带有 rxJs 6.0 的类型化 Observable?【英文标题】:How do I use catchError() and still return a typed Observable with rxJs 6.0? 【发布时间】:2018-10-19 02:08:58 【问题描述】:cd所以我正在尝试将我的一些 Angular 5 代码迁移到 6,并且我了解 rxjs 使用 .pipe() 运算符工作所需的大部分更改。它可以像您期望的“pipable”操作一样工作。
但是,catchError()
的行为不同于 .catch()
运算符。在 rxjs 6 之前,我使用 .catch()
运算符将错误输入转换为一致的错误对象,然后可以在 `.subscribe() 中捕获该对象。
getAlbums(): Observable<Album[]>
return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
.map(albumList => this.albumList = albumList)
.catch(new ErrorInfo().parseObservableResponseError);
new ErrorInfo().parseObservableResponseError
是一个函数,它将错误对象作为输入,并将输入错误解析为具有规范化对象的更简单的错误对象。捕获返回Observable<any>
:
parseObservableResponseError(response): Observable<any>
let err = new ErrorInfo();
...
return Observable.throw(err);
这对于轻松处理 rxjs5 上的错误非常有用 - 错误基本上被捕获为管道的一部分,然后抛出一个众所周知的错误结构,可以捕获 .subscribe()
错误函数。
但是,将相同的代码移动到 rxjs 6 并使用 .pipe()
我正在尝试执行以下操作:
getAlbums(): Observable<Album[]>
return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
.pipe(
map(albumList => this.albumList = albumList),
catchError(new ErrorInfo().parseObservableResponseError)
);
但这不起作用,因为 catchError 现在将Observable<any>
的结果返回到管道中,这不是我想要的。本质上,我只是想像以前一样重新抛出任何错误。
错误 TS2322:类型 'Observable' 不能分配给类型 'Observable'
如何模拟老算子.catch()
behavior?
更新:
在解决了这个问题之后,显示的代码刚刚开始工作,没有给我一个构建错误。老实说,我不知道为什么它之前失败并显示错误消息,但现在正在工作。 @cartant 在 cmets 中的建议是一种明确的方式来指定结果,并且效果也很好。
【问题讨论】:
如果你只是抛出新的 ErrorInfo()。 parseObservableResponseError(e) 而不是返回它? 为什么不 catchError((e:any)=> return Observable.of( success: false, error: true ));?或 catchError((e:any)=> return Observable.throw(e.error))) @Eliseo 这偶尔会起作用,但主要问题是你会得到一个返回类型,它是 observable 的原始类型(可能是 HttpResponse)和这个“成功/失败”结构的联合。即,如果您继续使用链,您将拥有HttpResponse | success: boolean, error: any
。然后,您需要在它之后添加一个额外的“映射”来规范化类型。我已经尝试过了,这是一个巨大的痛苦。 catchError 的重点是如果没有错误就不会调用它!
【参考方案1】:
您应该能够显式指定catchError
的类型参数,以表明它不会返回发出值的可观察对象——也就是说,它将返回Observable<never>
——并且总是会抛出:
getAlbums(): Observable<Album[]>
return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
.pipe(
map(albumList => this.albumList = albumList),
catchError<Album[], never>(new ErrorInfo().parseObservableResponseError)
);
这样做会看到从pipe
调用推断的类型为Observable<Album[]>
。
【讨论】:
catchError
应该真的有一个重载签名,以便如果传递的函数的返回类型是 never
则推断出正确的结果 - 即总是抛出。我想是时候创建另一个 PR了。以上是关于如何使用 catchError() 并且仍然返回带有 rxJs 6.0 的类型化 Observable?的主要内容,如果未能解决你的问题,请参考以下文章
在 catchError 之后不会执行 redux-observable
在 catchError 中发出多个操作 - Redux Observable
从角度服务通过管道传输时,rxjs catchError 不起作用
StreamProvider<User> 监听的 _MapStream<FirebaseUser, User> 抛出异常,但未提供`catchError`