bagaimana membuangError di switchMap di efek ngrx
Saya menggunakan ngrx8, rxjs6 dan angular 9
Setelah login saya perlu menelepon layanan lain. ketika layanan itu melempar kesalahan saya ingin menangkap kesalahan bagian dari efek saya untuk menanganinya, masalahnya adalah saya menangkap kesalahan dalam mencoba menangkap dan saya melihat log, tetapi catchError
tidak dipicu.
Kode yang disederhanakan
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 }));
}),
);
});
Kode asli saya
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 }));
}),
);
});
keluaran konsol

Jawaban
Daripada menggunakan Async-Await
sintaks untuk menunggu pengembalian Promise
oleh matrixService.initClient
selesai (yang tidak akan berfungsi dalam konteks saat ini karena switchMap
operator tidak menunggu async
fungsi), pertimbangkan untuk mengembalikannya tanpa menunggu, karena akan diubah menjadi Observable
(terima kasih kepada switchMap
operator menerima Promise
) sehingga this.userService.login
ditunggu.
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 }));
})
)
);
berdasarkan komentar saya akan sedikit mengubah jawaban sebelumnya
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 }));
})
)
);
Saya mengganti urutan, selalu menembak AuthActions.loginSuccess()
dan kemudian this.matrixService.initClient(userName, password)
.
catchError
tidak perlu dipanggil dua kali, kesalahan yang dihasilkan dari panggilan layanan akan tertangkap di catchError
operator terluar .