วิธี throwError ใน switchMap ในเอฟเฟกต์ ngrx
ฉันใช้ 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 }));
}),
);
});
เอาต์พุตคอนโซล

คำตอบ
แทนที่จะใช้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 }));
})
)
);
ตามความคิดเห็นฉันจะแก้ไขคำตอบก่อนหน้าเล็กน้อย
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
ดำเนินการด้านนอกสุด