Как выбросить ошибку из оператора карты 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 object) не имеет "bearerToken", я хочу выбросить ошибку. Так что в моей подписке он переходит во второй параметр (handleError), упомянутый ниже.
.subscribe(success, handleError)
Какие-либо предложения?
Ответы
Ответ 1
Просто скинуть ошибку внутри оператора map()
. Все обратные вызовы в RxJS заключены в блоки try-catch, поэтому они будут перехвачены, а затем отправлены как уведомление error
.
Это означает, что вы ничего не возвращаете и просто выдаете ошибку:
map(res => {
if (res.bearerToken) {
return this.saveJwt(res.bearerToken);
} else {
throw new Error('Valid token not returned');
}
})
throwError()
(ранее Observable.throw()
в RxJS 5) - это Observable, который просто отправляет уведомление error
но map()
не волнует, что вы возвращаете. Даже если вы вернете Observable из map()
он будет передан в качестве next
уведомления.
Последнее, что вам, вероятно, не нужно использовать .catchError()
(ранее catch()
в RxJS 5). Если вам необходимо выполнить какие-либо побочные эффекты в случае возникновения ошибки, лучше использовать, например, tap(null, err => console.log(err))
(прежний do()
в RxJS 5).
Январь 2019: обновлено для RxJS 6
Ответ 2
Если вам кажется, что 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
.
Ответ 3
Попробуй это
Observable.throw(new Error('error!'));