วิธี throwError ใน switchMap ในเอฟเฟกต์ ngrx

Aug 19 2020

ฉันใช้ ngrx8, rxjs6 และเชิงมุม 9

หลังจากเข้าสู่ระบบฉันต้องเรียกใช้บริการอื่น เมื่อบริการนั้นเกิดข้อผิดพลาดฉันต้องการให้ส่วน catchError ของฉันจัดการกับมันปัญหาคือฉันตรวจพบข้อผิดพลาดในการลองจับและฉันเห็นบันทึก แต่catchErrorไม่ถูกทริกเกอร์

โค้ดแบบง่าย

    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 }));
            }),
        );
    });

รหัสจริงของฉัน

    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 }));
            }),
        );
    });

เอาต์พุตคอนโซล

คำตอบ

1 RafiHenig Aug 19 2020 at 04:23

แทนที่จะใช้Async-Awaitไวยากรณ์เพื่อรอให้Promiseส่งคืนโดยmatrixService.initClientเสร็จสมบูรณ์ (ซึ่งจะไม่ทำงานในบริบทปัจจุบันเนื่องจากswitchMapตัวดำเนินการไม่รอasyncฟังก์ชั่น) ให้พิจารณาส่งคืนโดยไม่ต้องรอเพราะจะถูกแปลงเป็นObservable(ขอบคุณswitchMapตัวดำเนินการ ยอมรับPromise) ส่งผลให้เกิดthis.userService.loginการรอคอย

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

ตามความคิดเห็นฉันจะแก้ไขคำตอบก่อนหน้าเล็กน้อย

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 }));
    })
  )
);

ฉันเปลี่ยนคำสั่งที่มักจะยิงแล้วAuthActions.loginSuccess()this.matrixService.initClient(userName, password)

catchErrorไม่จำเป็นต้องเรียกสองครั้งข้อผิดพลาดใด ๆ ที่เกิดจากการเรียกใช้บริการจะถูกจับในตัวcatchErrorดำเนินการด้านนอกสุด