Я хочу, чтобы оператор карты моего наблюдаемого объекта выдавал ошибку в зависимости от условия. Например, если правильные данные 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)
Какие-либо предложения?
angular
typescript
rxjs
Хасан
источник
источник
throw 'Valid token not returned';
?return throw 'message here'
но работает безreturn
ключевого слова. Позвольте мне проверить, правильно ли он работает логически.subscribe
методе, и.finally()
в потоке также срабатывает триггер. (Однако казнь остановлена, и это хорошо)Ответы:
Просто выкинь ошибку внутри
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
источник
return
оттуда достать объект ошибки и теперь он отлично работает :) Спасибо!catch()
только для регистрации и повторной выдачи ошибки, что не нужно, если вы просто хотите выполнить побочный эффект (регистрацию ошибки), и его проще использовать, простоdo()
return throwError(new Error('Valid token not returned'));
?return throwError()
возвращаетObservable<never>
, это просто немедленно прерывает наблюдаемый поток, не возвращаясь вообще.Если вам кажется, что это
throw new Error()
кажется ненаблюдаемым, вы можете использоватьthrowError(...)
withswitchMap
вместоmap
(разница в том, чтоswitchMap
возвращает новое наблюдаемое):// this is the import needed for throwError() import { throwError } from 'rxjs'; // 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 is } });
или более кратко:
this.httpPost.pipe(switchMap(res => (res.bearerToken) ? of(this.saveJwt(res.bearerToken)) : throwError('Valid token not returned') ));
Поведение будет таким же, просто другой синтаксис.
Вы буквально говорите «переключиться» с наблюдаемого http в конвейере на другое наблюдаемое, которое либо просто «обертывает» выходное значение, либо обнаруживает новую наблюдаемую «ошибку».
Не забудьте указать,
of
иначе вы получите запутанные сообщения об ошибках.Кроме того, прелесть switchMap заключается в том, что вы можете вернуть целую новую «цепочку» команд, если хотите - для любой логики, с которой нужно работать
saveJwt
.источник
switchMap
об асинхронномif
утверждении - все стало намногоХотя на этот вопрос уже дан ответ, я хотел бы поделиться своим подходом (хотя он лишь немного отличается от приведенного выше).
Я бы решил, что будет возвращено отдельно от отображения, и наоборот. Я не уверен, какой оператор лучше всего подходит для этого, поэтому буду использовать
tap
.this.httpPost.pipe( tap(res => { if (!res.bearerToken) { throw new Error('Valid token not returned'); } }), map(res => this.saveJwt(res.bearerToken)), );
источник
tap
игнорируется. этот код делает не то, что написаноthrow new Error()
это лучший вариант на данный момент