【问题标题】:Is it impossible to catch errors inside a subscription?是否不可能在订阅中捕获错误?
【发布时间】:2019-08-19 09:18:25
【问题描述】:

我正在使用 Angular 7,我试图捕捉抛出的错误,因为外部 api 返回的值在我期望的值处具有空值。

我似乎无法弄清楚在这种情况下我应该做什么。

我有一个调用 api 的服务。

getObjectValue(param: paramtype): Observable<ObjectValue> {
    return this.http.get<objectwithvalues>(environment.baseapiurl + '/api/object/value/'+ param);
  }

在消费组件中我像往常一样订阅

testfunction() {
   this.service.getObjectValue().Subscribe(v => {
    *DO STUFF*
    *Error happens* v['o'] // oh no v is null
   },
    error=>{
     console.log('error') 
     this.snackbar.open('this went wrong' + error); 
    }
  );
}

这是基本情况。 这样做不会触发 'error=>{}' Angular 只是吐出一条错误消息。

所以我在订阅回调范围内尝试了 try/catch。没抓到。

我目前正在尝试将服务代码更改为以下

getObjectValue(param: paramclass): Observable<ObjectValue> {
    return this.http.get<EventWifi>(
      environment.baseapiurl + '/api/object/value/'+ param).pipe(map(v=> {
   if(v === null){
     return throwError('v is null');  
   } 
  }),
   catchError(err => this.errorTest(err))
);
  }

this.errorTest(err: any): Observable<any> {
 return throwError(err);

}

虽然在订阅者中执行相同操作,但订阅错误函数从未捕获到错误,因此我无法正确处理错误。

使用最新显示的服务功能,根本不会引发任何错误。

我已经尝试了这么多配置上的小差异,我现在几乎记不得了,所以一定有一个基本的东西我搞砸了。

我看过这么多例子,但没有一个能在我的案例中找到并起作用。

【问题讨论】:

  • 我认为 HttpInterceptor 将彻底解决您的问题。只需研究并将其导入您的项目。

标签: angular error-handling rxjs try-catch observable


【解决方案1】:

问题是您正在尝试处理订阅函数中的错误。这永远不会达到您的错误功能,很简单,因为它不能。您应该从管道中抛出错误。最好在mergeMap:

getObjectValue(param: paramtype): Observable<ObjectValue> {
  return this.http.get(environment.baseapiurl + '/api/object/value/'+ param).pipe(
    mergeMap((v) => v == null ? throwError('v is null') : of(v)) 
  );
}

然后你可以这样做:

testfunction() {
  this.service.getObjectValue().subscribe((v) => {
    // v will never be null
  },
  (error) => {
    console.log('error') 
    this.snackbar.open('this went wrong' + error); 
  });
}

如果这是在您的应用程序中经常发生的事情,您可以创建一个 HttpInterceptor 来为您执行此操作。如果返回值为null,你可以让它抛出带有特定错误代码和数字的http调用。

【讨论】:

  • 感谢您的帮助,它奏效了,真是如释重负。如果再次出现,我会记住拦截器。只是为了澄清所以我使用了 map ,它会返回一个 observable 的 observable,并且“消费”组件没有订阅内部 observable,因此我没有收到错误。但是使用 mergemap 它将可观察对象合并为一个,然后进行评估并返回新的可观察对象of(v),如果它不为空,则抛出错误。如果这有意义的话。
  • @Mikkel 你的思路是正确的:)。很高兴我能帮忙
【解决方案2】:

您的错误是您在 map 中执行 throwError 时返回了 Observable 的 Observable,请改用 mergeMap

return this.http.get<EventWifi>(url).pipe(mergeMap(v=> {
   if(v === null){
     return throwError('v is null');  
   } else {
        return of(v)
   } 
})

在订阅下,Observable 不是错误。

https://stackblitz.com/edit/angular-uglwbm

【讨论】:

    猜你喜欢
    • 2021-11-27
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 2018-09-21
    • 2012-07-12
    • 2011-06-18
    相关资源
    最近更新 更多