【问题标题】:How do I use catchError() and still return a typed Observable with rxJs 6.0?如何使用 catchError() 并且仍然返回带有 rxJs 6.0 的类型化 Observable?
【发布时间】: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&lt;any&gt;

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&lt;any&gt; 的结果返回到管道中,这不是我想要的。本质上,我只是想像以前一样重新抛出任何错误。

错误 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 的重点是如果没有错误就不会调用它!

标签: angular typescript typescript-typings rxjs6


【解决方案1】:

您应该能够显式指定catchError 的类型参数,以表明它不会返回发出值的可观察对象——也就是说,它将返回Observable&lt;never&gt;——并且总是会抛出:

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&lt;Album[]&gt;

【讨论】:

  • catchError 应该真的有一个重载签名,以便如果传递的函数的返回类型是 never 则推断出正确的结果 - 即总是抛出。我想是时候创建另一个 PR了。
猜你喜欢
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-17
  • 2021-12-06
  • 2019-08-05
相关资源
最近更新 更多