ngrx效果中switchMap如何抛出错误
how to throwError in switchMap in the ngrx effect
我正在使用 ngrx8、rxjs6 和 angular 9
登录后我需要调用另一个服务。当该服务抛出错误时,我想 catchError 我的效果的一部分来处理它,问题是我在 try catch 中捕获了错误并且我看到了日志,但是 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
语法等待 matrixService.initClient
返回的 Promise
完成(由于 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
运算符中被捕获。
我正在使用 ngrx8、rxjs6 和 angular 9
登录后我需要调用另一个服务。当该服务抛出错误时,我想 catchError 我的效果的一部分来处理它,问题是我在 try catch 中捕获了错误并且我看到了日志,但是 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
语法等待 matrixService.initClient
返回的 Promise
完成(由于 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
运算符中被捕获。