如何从RxJS映射运算符抛出错误(angular)

时间:2017-04-04 06:17:40

标签: angular typescript rxjs

我想根据条件从我的可观察地图运算符中抛出错误。例如,如果未收到正确的API数据。请参阅以下代码:

private userAuthenticate( email: string, password: string ) {
    return this.httpPost(`${this.baseApiUrl}/auth?format=json&provider=login`, {userName: email, password: password})
        .map( res => { 
            if ( res.bearerToken ) {
                return this.saveJwt(res.bearerToken); 
            } else {
                // THIS DOESN'T THROW ERROR --------------------
                return Observable.throw('Valid token not returned');
            }
        })
        .catch( err => Observable.throw(this.logError(err) )
        .finally( () => console.log("Authentication done.") );
}

基本上你可以在代码中看到,如果响应(res对象)没有bearerToken'我想抛出一个错误。所以在我的订阅中它会进入下面提到的第二个参数(handleError)。

.subscribe(success, handleError)

有什么建议吗?

4 个答案:

答案 0 :(得分:85)

将错误抛出map()运算符。 RxJS中的所有回调都包含try-catch块,因此它将被捕获,然后作为error通知发送。

这意味着你不会返回任何内容而只是抛出错误:

map(res => { 
  if (res.bearerToken) {
    return this.saveJwt(res.bearerToken); 
  } else {
    throw new Error('Valid token not returned');
  }
})

throwError()(RxJS 5中的前Observable.throw())是一个只发送error通知的Observable,但map()并不关心您返回的内容。即使您从map()返回Observable,也会将其作为next通知传递。

最后,您可能不需要使用.catchError()(RxJS 5中的前catch())。如果您在发生错误时需要执行任何副作用,最好使用tap(null, err => console.log(err))(RxJS 5中的前do())。

2019年1月:更新了RxJS 6

答案 1 :(得分:1)

如果您觉得throw new Error()似乎不可观察,则可以使用switchMap

// RxJS 6+ syntax
this.httpPost.pipe(switchMap(res => { 
   if (res.bearerToken) {
      return of(this.saveJwt(res.bearerToken)); 
   } 
   else {
      return throwError('Valid token not returned');
   }
});

或更简洁:

this.httpPost.pipe(switchMap(res => (res.bearerToken) ? 
                                    of(this.saveJwt(res.bearerToken)) : 
                                    throwError('Valid token not returned')
));

行为将相同,只是语法不同。

您的意思是说从管道中的http可观察值“切换”到另一个可观察值,即只是“包装”输出值或新的“错误”可观察值。

别忘了放of,否则您会得到一些令人困惑的错误消息。

“ switchMap”的优点还在于,如果需要,您可以返回一条全新的“链”命令-对于需要使用saveJwt完成的任何逻辑。

答案 2 :(得分:0)

答案 3 :(得分:-1)

即使已经回答了这个问题,我也想分享我自己的方法(即使与上面的方法略有不同)。

我将决定从映射中返回什么,反之亦然。我不确定哪种运算符最适合此操作,所以我将使用tap

this.httpPost.pipe(
  tap(res => { 
    if (!res.bearerToken) {
      throw new Error('Valid token not returned');
    }
  }),
  map(res => this.saveJwt(res.bearerToken)),
);