come lanciareErrore in switchMap nell'effetto ngrx
Sto usando ngrx8, rxjs6 e angular 9
Dopo il login devo chiamare un altro servizio. quando quel servizio sta generando un errore, voglio catchError parte del mio effetto per gestirlo, il problema è che rilevo l'errore in try catch e vedo il registro, ma catchError
non viene attivato.
Codice semplificato
login$ = createEffect(() => {
return this.actions$.pipe(
ofType(AuthActions.login),
switchMap((action) =>
this.userService.login(action.userName, action.password)
.pipe(
switchMap((token) => {
return throwError(new Error('hello'));
}),
map((token) => AuthActions.loginSuccess()),
catchError((error) => {
console.error('error', error); // I don't see this in console
return of(AppError({ error }));
})),
),
catchError((error) => {
console.error('error 2', error);
return of(AppError({ error }));
}),
);
});
Il mio vero codice
login$ = createEffect(() => {
return this.actions$.pipe(
ofType(AuthActions.login),
switchMap((action) =>
this.userService.login(action.userName, action.password)
.pipe(
switchMap(async (token) => {
try {
await this.matrixService.initClient(action.userName, action.password);
return of(token);
}
catch (error) {
console.log('catch error', error); // I see this in console
return throwError(error);
}
}),
map((token) => AuthActions.loginSuccess()),
catchError((error) => {
console.error('error', error); // I don't see this in console
return of(AppError({ error }));
})),
),
catchError((error) => {
console.error('error 2', error);
return of(AppError({ error }));
}),
);
});
uscita della console

Risposte
Piuttosto che utilizzare Async-Await
la sintassi per attendere il completamento Promise
di restituito da matrixService.initClient
(che non funzionerebbe nel contesto corrente a causa switchMap
dell'operatore che non attende async
le funzioni), considera di restituirlo senza attenderlo, poiché verrebbe convertito in un Observable
(grazie a switchMap
operator accettare Promise
) risultando in this.userService.login
attesa.
login$ = createEffect(() => this.actions$
.pipe(
ofType(AuthActions.login),
switchMap(({ userName, password }) => this.userService.login(userName, password)
.pipe(
switchMap(() => this.matrixService.initClient(userName, password)),
map((token) => AuthActions.loginSuccess()),
catchError((error) => {
console.error('error', error);
return of(AppError({ error }));
})
)
),
catchError((error) => {
console.error('error 2', error);
return of(AppError({ error }));
})
)
);
in base ai commenti modificherò un po 'le risposte precedenti
login$ = createEffect(() => this.actions$
.pipe(
ofType(AuthActions.login),
switchMap(({ userName, password }) => this.userService.login(userName, password)
.pipe(
map((token) => AuthActions.loginSuccess())
tap(() => this.matrixService.initClient(userName, password)),
)
),
catchError((error) => {
console.error('error 2', error);
return of(AppError({ error }));
})
)
);
Cambio l'ordine, sparo sempre AuthActions.loginSuccess()
e poi this.matrixService.initClient(userName, password)
.
catchError
non ha bisogno di essere chiamato due volte, qualsiasi errore generato dalla chiamata di servizio verrà rilevato nell'operatore più esterno catchError
.