如何从RxJS体系的store dispatch调用中提取返回的userId
解决方案
你当前用的是NgRx状态管理框架,核心逻辑是 dispatch方法本身是同步无返回值的,所有异步操作的结果都会通过成功/失败Action广播,你需要的userId会放在createUserActionSuccess的payload中,可以通过两种方式拿到:
方案1:在组件中监听成功Action(适合后续请求和当前页面/组件强相关的场景)
- 先在组件中注入
Actions服务,和你Effect中使用的是同一个服务:
import { Actions, ofType } from '@ngrx/effects'; import { take } from 'rxjs'; constructor( // 保留你原本的其他注入 private actions$: Actions, private router: Router ) {}
- 修改提交逻辑,先订阅成功事件再分发创建Action:
if (!this.id) { // 先监听单次创建成功事件 this.actions$.pipe( ofType(fromUserManagement.createUserActionSuccess), take(1) // 只触发一次,自动销毁订阅避免内存泄漏 ).subscribe(successAction => { // 从成功Action的payload中拿到后端返回的用户数据,提取userId const newUserId = successAction.payload.id; // 这里执行你需要的两个后续请求 this.yourFirstRequest(newUserId); this.yourSecondRequest(newUserId); // 所有逻辑执行完成后再跳转页面 this.router.navigateByUrl('/app/users/list'); }) // 订阅完成后再分发创建用户的Action this.store.dispatch(fromUser.createUserAction({ result } as any)); }
- 调整Effect逻辑,删除原本的跳转代码,避免页面提前跳转导致组件销毁、订阅不生效:
map(response => { this.messageService.open('User has been created!', 'success'); // 删掉下面这行跳转,移到组件的成功回调中执行 // this.router.navigateByUrl('/app/users/list'); return fromUserManagement.createUserActionSuccess(response) }),
方案2:在Effect中处理后续请求(适合后续请求是通用业务逻辑、和当前组件无关的场景)
直接修改createUser$ Effect,在创建成功后链式调用后续请求,不需要修改组件代码:
import { forkJoin, of } from 'rxjs'; import { mergeMap, catchError } from 'rxjs/operators'; createUser$ = createEffect(() => this.actions$.pipe( ofType(fromUserManagement.createUserAction), mergeMap((action) => { return this.identityServiceClient.create(action.result).pipe( mergeMap(response => { this.messageService.open('User has been created!', 'success'); const newUserId = response.id; // 并行执行两个后续请求,全部完成后再跳转 return forkJoin([ this.yourFirstService.request(newUserId), this.yourSecondService.request(newUserId) ]).pipe( map(() => { this.router.navigateByUrl('/app/users/list'); return fromUserManagement.createUserActionSuccess(response); }) ) }), catchError(() => { this.messageService.open('Something went wrong!', 'danger'); return of(fromUserManagement.createUserActionError()); }) ); }) ) )
注意事项
- 不要依赖
setTimeout做异步等待,所有NgRx的异步结果都可以通过订阅Action或者Store状态实现可靠监听,你原本编辑用户逻辑里的setTimeout也可以替换成监听editUserActionSuccess实现,避免超时时间不准的问题。 - 组件中的RxJS订阅需要处理销毁逻辑,上面示例中用了
take(1),执行一次后会自动取消订阅,不会产生内存泄漏;如果是长期订阅需要配合takeUntil(this.destroy$)的方式处理。
内容的提问来源于stack exchange,提问作者Paweł Wąsowski
相关产品推荐
相关产品推荐

