使用泛型时如何在Angular HTTPClient.post()中捕获错误

时间:2018-07-21 14:42:36

标签: angular

这个问题在SO上被询问了大约1万亿次,但没有一个帖子回答我的问题。所以我再问一次。

以下是我的方法(在service中),该方法发出了发布请求。

  makePostReq<T>(reqObj: {url:string, body:any, headerData?:any}): Observable<T>{
    let headers = this.createHeaders(reqObj.headerData);
    return this.httpClient.post<T>(reqObj.url, reqObj.body, {headers:headers})
      .catch((e: any ) => {
        console.log(e);
        this.utilityService.showErrorToaster(e);
      });
  }

该方法希望捕获HTTPError,然后将其记录下来,然后向用户显示有关该错误的烤面包机/警报。

问题:

以上代码给出此错误:

TS2345: Argument of type '(e: any) => void' is not assignable to parameter of type '(err: any, caught: Observable<T>) => ObservableInput<{}>'.   Type 'void' is not assignable to type 'ObservableInput<{}>'.

我已经知道:

我完全知道为什么会出现此错误。我知道catch应该返回类型Observable<T>的对象,但是我没有任何返回类型T的对象。返回Observable.of(null)也不起作用。 我也知道,如果删除通用的<T>,我不会收到此编译错误。

我的问题:

如何在不损害generics的情况下使上述代码正常工作。

1 个答案:

答案 0 :(得分:0)

我认为在makePostReq<T>(...)中捕获错误的整个想法是令人误解的。

这是为什么。

首先,通过返回Observable<T>,我们说我们的方法将在某个时刻(当内部的http调用响应时)发出T类型的值。如果我们处理makePostReq<T>(...)内的错误,则必须发出T的伪实例(例如null)来满足我们的编译器要求。这意味着您还必须通过过滤掉null(类似于makePostReq<string>(...).pipe(filter(str => str !== null)))来在调用者中处理此问题,这意味着您实际上可以两次处理错误,而您只能在调用者中处理异常像makePostReq<string>(...).pipe(catchError(error => utilityService.showErrorToaster(error)))

其次,通过使您的呼叫通用,我假设您打算从各种服务/针对各种类型的T进行呼叫。通过处理makePostReq<T>(...)内部的错误并调用this.utilityService.showErrorToaster(e);,您就可以将错误处理限制为仅弹出Toast通知,而没有其他任何操作。如果某个时候您需要重定向到错误页面,而又想做一些不同的事情怎么办?与调用者仅进行错误处理相比,使用此设置将更加困难。

所以我建议您将其保留为

 makePostReq<T>(reqObj: {url:string, body:any, headerData?:any}): Observable<T>{
    let headers = this.createHeaders(reqObj.headerData);
    return this.httpClient.post<T>(reqObj.url, reqObj.body, {headers:headers});
  }