我想根据条件从我的可观察地图运算符中抛出错误。例如,如果未收到正确的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)
有什么建议吗?
答案 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)
理解throwError()的区别不是抛出错误 https://medium.com/angular-in-depth/throwerror-is-not-throw-error-ad6c76c53377
答案 3 :(得分:-1)
即使已经回答了这个问题,我也想分享我自己的方法(即使与上面的方法略有不同)。
我将决定从映射中返回什么,反之亦然。我不确定哪种运算符最适合此操作,所以我将使用tap
。
this.httpPost.pipe(
tap(res => {
if (!res.bearerToken) {
throw new Error('Valid token not returned');
}
}),
map(res => this.saveJwt(res.bearerToken)),
);