angular - Hvordan bruker jeg catchError() og likevel returnerer et typet Observable med rxJs 6.0?
Så jeg prøver å migrere noe av Angular 5-koden min til 6, og jeg forstår de fleste av endringene som kreves for at rxjs skal fungere ved bruk av .pipe() operatoren. Det fungerer som du forventer for 'pipable' operasjoner.
Imidlertid er oppførselen til catchError() annerledes enn .catch()-operatoren. Før rxjs 6 brukte jeg .catch()-operatoren for å omdanne feilen som ble sendt inn til et konsistent feilsobjekt som deretter kan fanges i `.subscribe().
getAlbums(): Observable<Album[]> {
return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
.map(albumList => this.albumList = albumList)
.catch(new ErrorInfo().parseObservableResponseError);
}
new ErrorInfo().parseObservableResponseError er en funksjon som tar et feilmelding-objekt som input og analyserer input-feilen til et enklere feilmelding-objekt med et normalisert objekt. Catch returnerer Observable<any>:
parseObservableResponseError(response): Observable<any> {
let err = new ErrorInfo();
...
return Observable.throw(err);
}
Dette fungerte flott for å enkelt håndtere feil opp til rxjs5 - feil fanges stort sett som en del av pipelinen og kaster deretter en velkjent feilstruktur som kan fanges i .subscribe() feilsfunksjon.
Å flytte den samme koden til rxjs 6, og bruke .pipe(), prøver jeg å gjøre følgende:
getAlbums(): Observable<Album[]> {
return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
.pipe(
map(albumList => this.albumList = albumList),
catchError(new ErrorInfo().parseObservableResponseError)
);
}
Dette fungerer imidlertid ikke fordi catchError nå returnerer et resultat av Observable<any> inn i pipeline, noe som ikke er det jeg ønsker her. I bunn og grunn vil jeg bare kaste eventuelle feil på nytt som jeg gjorde før.
feil TS2322: Type 'Observable<{} | Album[]>' kan ikke tildeles til type 'Observable'
Hvordan kan man simulere den gamle operatoren .catch() oppførsel?
Oppdatering:
Etter å ha lekt litt mer med dette, begynte koden som vist å fungere uten å gi meg en byggefeil. Ærlig talt har jeg ingen idé om hvorfor den feilet med feilmeldingen før, men den fungerer nå. Forslaget fra @cartant i kommentarene er en eksplisitt måte å spesifisere resultatet på, og det fungerer også.
Svar #1
Du bør kunne eksplisitt spesifisere typeparametrene til catchError for å indikere at det ikke vil returnere en observabel som sender ut en verdi - det vil si, det vil returnere Observable<never> - og vil alltid kaste:
getAlbums(): Observable<Album[]> {
return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
.pipe(
map(albumList => this.albumList = albumList),
catchError<Album[], never>(new ErrorInfo().parseObservableResponseError)
);
}
Å gjøre det vil få typen som er utledet fra pipe-kallet til å være Observable<Album[]>.
Svar #2
Du kan returnere et typet observable med:
return of (new YourType({ }));
i stedet for
return throwError(()=>err);
For eksempel:
http.get<CustomType>().pipe(
map(result=>{
// do something here, such as accessing local storage, stopping a spinner...etc.
return result;
}),
catchError(err => {
return of (new CustomType({
//initialization with a constructor
}));
// or you can return throwError(err);
})
)
