bagaimana membuangError di switchMap di efek ngrx

Aug 19 2020

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 catchErrortidak 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

1 RafiHenig Aug 19 2020 at 04:23

Daripada menggunakan Async-Awaitsintaks untuk menunggu pengembalian Promiseoleh matrixService.initClientselesai (yang tidak akan berfungsi dalam konteks saat ini karena switchMapoperator tidak menunggu asyncfungsi), pertimbangkan untuk mengembalikannya tanpa menunggu, karena akan diubah menjadi Observable(terima kasih kepada switchMapoperator menerima Promise) sehingga this.userService.loginditunggu.

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 }));
    })
  )
);
HamzaZaidi Aug 19 2020 at 22:01

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).

catchErrortidak perlu dipanggil dua kali, kesalahan yang dihasilkan dari panggilan layanan akan tertangkap di catchErroroperator terluar .