我想根据一个条件,从我的 observable's map操作符中抛出一个错误。例如,如果没有收到正确的 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)
有什么建议吗?
只需在 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())是一个 Observable,它只会发送 "错误 "通知,但
map()并不关心你返回了什么。即使您从
map()返回一个 Observable,它也会作为
next` 通知传递。
最后,您可能不需要使用 .catchError()
(RxJS 5 中的前身 catch()
)。如果需要在错误发生时执行任何副作用,最好使用 tap(null, err => console.log(err))
(RxJS 5 中以前的 do()
)。
2019 年 1 月:针对 RxJS 6 进行了更新
如果你觉得 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
完成的逻辑。
尽管这个问题已经有人回答过了,但我还是想分享一下我自己的方法(尽管与上面的方法略有不同)。
我会在映射之外决定返回的内容,反之亦然。我不确定哪种运算符最合适,所以我会使用 tap
。
this.httpPost.pipe(
tap(res => {
if (!res.bearerToken) {
throw new Error('Valid token not returned');
}
}),
map(res => this.saveJwt(res.bearerToken)),
);