使用switchMap调用服务时出现UnsubscriptionErrorImpl错误
解决RxJS + NgRx Effect中的UnsubscriptionError问题
报错信息
UnsubscriptionErrorImpl {message: "1 errors occurred during unsubscription:\n1) TypeEr…not read properties of undefined (reading 'type')", name: 'UnsubscriptionError', errors: Array(1)}
现有代码
Effect 代码
loadUserProfile$ = createEffect(() => this.actions.pipe( ofType(ActionTypes.LoadUserProfile), take(1), switchMap (_ => this.userProfileService.getUserProfile().pipe(take(1), tap(res => console.log(res))) )));
UserProfileService 代码
public getUserProfile(): Observable<any> { return this.httpClient.get(this.accountBaseUrl + '/admin/users/me'); }
问题原因
这个错误的核心是Effect没有返回正确的Action流。NgRx Effect要求内部Observable必须发出Action类型的值,当前代码里switchMap返回的是HTTP请求的Observable,仅通过tap打印响应,没有将结果映射为Action。当这个Observable完成时,Effect的订阅逻辑因未拿到预期的Action值,触发取消订阅时的类型错误。
修复方案
1. 映射请求结果为Success Action
假设你已定义LoadUserProfileSuccess类型的Action,修改Effect代码如下:
loadUserProfile$ = createEffect(() => this.actions.pipe( ofType(ActionTypes.LoadUserProfile), take(1), switchMap(_ => this.userProfileService.getUserProfile().pipe( take(1), tap(res => console.log(res)), // 将接口响应映射为成功Action map(profile => ({ type: ActionTypes.LoadUserProfileSuccess, payload: profile })) ) ) ) );
2. 可选:添加错误处理逻辑
为避免请求失败时错误扩散,可加入catchError返回错误Action:
loadUserProfile$ = createEffect(() => this.actions.pipe( ofType(ActionTypes.LoadUserProfile), take(1), switchMap(_ => this.userProfileService.getUserProfile().pipe( take(1), tap(res => console.log(res)), map(profile => ({ type: ActionTypes.LoadUserProfileSuccess, payload: profile })), catchError(error => of({ type: ActionTypes.LoadUserProfileFailure, payload: error.message }) ) ) ) ) );
说明
NgRx Effect的本质是"Action到Action"的流转,必须将异步操作的结果转换成对应Action供Reducer处理。如果Effect未返回合法的Action流,内部订阅逻辑会因值类型不匹配触发取消订阅错误。
内容的提问来源于stack exchange,提问作者Kaustubh Raghavan
相关产品推荐
相关产品推荐

