Chcę zgłosić błąd z operatora mapy mojego obserwowalnego na podstawie warunku. Na przykład, jeśli nie otrzymano poprawnych danych API. Zobacz poniższy kod:
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.") );
}
Zasadniczo, jak widać w kodzie, jeśli odpowiedź (obiekt res) nie ma „bearerToken”, chcę wyrzucić błąd. Więc w mojej subskrypcji trafia do drugiego parametru (handleError) wspomnianego poniżej.
.subscribe(success, handleError)
Jakieś sugestie?
angular
typescript
rxjs
Hassan
źródło
źródło
throw 'Valid token not returned';
?return throw 'message here'
ale działa bezreturn
słowa kluczowego. Sprawdzę, czy działa poprawnie logicznie.subscribe
metodzie, a.finally()
strumień w strumieniu również jest wyzwalany. (Jednak egzekucja zostaje zatrzymana, co jest dobre)Odpowiedzi:
Po prostu wrzuć błąd do wnętrza
map()
operatora. Wszystkie wywołania zwrotne w RxJS są opakowane blokami try-catch, więc zostaną przechwycone, a następnie wysłane jakoerror
powiadomienie.Oznacza to, że nic nie zwracasz i po prostu wyrzucasz błąd:
map(res => { if (res.bearerToken) { return this.saveJwt(res.bearerToken); } else { throw new Error('Valid token not returned'); } })
throwError()
(DawniejObservable.throw()
w RxJS 5) jest zauważalny, które po prostu wysyłaerror
powiadomienie, alemap()
nie obchodzi mnie to, czego wracać. Nawet jeśli zwrócisz zmap()
niego Observable , zostanie przekazane jakonext
powiadomienie.Ostatnia rzecz, prawdopodobnie nie musisz jej używać
.catchError()
(poprzedniocatch()
w RxJS 5). Jeśli potrzebujesz wykonać jakieś efekty uboczne, gdy wystąpi błąd, lepiej użyć na przykładtap(null, err => console.log(err))
(dawniejdo()
w RxJS 5).Sty 2019: Zaktualizowano dla RxJS 6
źródło
return
obiektu błąd z niego i teraz działa idealnie :) Dzięki!catch()
tylko do logowania i ponownego zgłaszania błędu, co jest niepotrzebne, jeśli chcesz tylko wykonać efekt uboczny (rejestrowanie błędu) i jest łatwiejsze w użyciu po prostudo()
return throwError(new Error('Valid token not returned'));
?return throwError()
zwraca anObservable<never>
, to po prostu natychmiast przerywa obserwowalny strumień, bez żadnego powrotu.Jeśli
throw new Error()
wydaje ci się, że wydaje się nieobserwowalne - tak jak możesz użyćthrowError(...)
zswitchMap
zamiastmap
(różnica polega na tym, żeswitchMap
zwraca nową obserwowalną):// 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 } });
lub bardziej zwięźle:
this.httpPost.pipe(switchMap(res => (res.bearerToken) ? of(this.saveJwt(res.bearerToken)) : throwError('Valid token not returned') ));
Zachowanie będzie takie samo, to po prostu inna składnia.
Dosłownie mówisz „przełącz” z http obserwowalnego w potoku na inną obserwowalną, która jest albo po prostu „zawijaniem” wartości wyjściowej, albo nowym obserwowalnym „błędem”.
Nie zapomnij wstawić
of
, bo otrzymasz mylące komunikaty o błędach.Piękno „switchMap” polega również na tym, że jeśli chcesz, możesz zwrócić cały nowy „łańcuch” poleceń - bez względu na to, z jaką logiką trzeba się uporać
saveJwt
.źródło
switchMap
o asynchronicznejif
wypowiedzi - rzeczy miały dużo więcej sensu :-)Chociaż na to pytanie już udzielono odpowiedzi, chciałbym podzielić się moim podejściem (chociaż różni się ono tylko nieznacznie od powyższego).
Zdecydowałbym, co jest zwracane niezależnie od mapowania i na odwrót. Nie jestem pewien, który operator jest najlepszy do tego, więc użyję
tap
.this.httpPost.pipe( tap(res => { if (!res.bearerToken) { throw new Error('Valid token not returned'); } }), map(res => this.saveJwt(res.bearerToken)), );
źródło
tap
jest ignorowana. ten kod działa inaczej niż mówithrow new Error()
opcja jest jak dotąd najlepsza