2

我正在使用角度的异步管道来监视来自 rxjs 商店的可观察对象。组件的 ngOnInit 看起来像这样

ngOnInit() {
  this.userRole$ = this.store.select(selectUserProfile).pipe(
    filter(user => !!user),
    map(user => parseUserRole(user.role))
  );
}

组件模板如下所示

<p> User role is {{ userRole$ | async }} </p>

用户登录后,页面消息为空字符串

在 component.ts 我添加了以下代码来调试问题

this.userRole$.subscribe(userRole => {
  alert(`new user role is ${userRole}`);
});

用户登录后,我收到一条警告说“新用户角色是管理员”,但是,html 模板中的管道没有更新。

当我使用 of() 将商店 select() 替换为虚拟值时,一切都按预期工作,所以我很确定问题与 rxjs 有关。

auth reducer(正在触发)看起来像这样(

export function reducer(state = initialAuthState, action: AuthActions): AuthState {
    switch (action.type) {
        /// ...CODE OMITTED
        case AuthActionTypes.UserProfileRetrieved:
            alert(`setting user profile ${action.payload.userProfile}`)
            return { ...state, userProfile: action.payload.userProfile }
        default:
            return state;
    }
}

我已经尝试确保从 ngZone.run() 内部调度 UserProfileRetrieved 操作,但这并没有什么不同。我真的不知道如何进行调试。任何指针将不胜感激。谢谢!

4

2 回答 2

1

你可以试试这个代码,看看它是否工作正常。添加了点击操作员以查看是否发生了从商店发出的此类更改/数据。

this.userRole$ = this.store
   .select(selectUserProfile)
   .pipe(
     tap(user => console.log('FETCHED:', user)),        // Console if user data exists
     filter(Boolean),                                   // Change !!user to Boolean
     tap(user => console.log('FILTERED:', user)),       // Console if user exists after filter 
     map(user => parseUserRole(user.role))
     tap(user => console.log('MAPPED:', user)),         // Console if user is mapped
   );

笔记:

商店只会在调用先前/父服务后发送它的响应。

例子:

// If along with the getUsers() functionality has a piped storeService in it
// http.get(url).pipe(tap(data => this.storeService.set('users', data)))
this.userService.getUsers().subscribe();    

// You can then initialize your store to get the data invoked/set above
this.user$ = this.store.select('users');
于 2020-02-02T02:52:17.223 回答
0

事实证明,这是由 auth0 本机应用程序登录流程的副作用引起的。应用路由器配置为使用基于哈希的路由以支持 Cordova。从 auth0 获取登录令牌后,我们正在清除哈希以删除令牌信息。在此之后的任何存储更新都不会反映在异步管道中,但在此之前的更新会反映。

如果有人遇到类似问题,请确保清除哈希是您在导航到授权后 URL 之前所做的最后一件事。感谢@Shorbag​​y 和@KShewengger 的帮助。

这是我用来执行此操作的代码

@Effect()
    loginComplete$ = this.actions$.pipe(
        ofType<LoginComplete>(AuthActionTypes.LoginComplete),
        exhaustMap(() => {
            return this.authService.authResult$.pipe(
                map((authResult: any) => {
                    if (environment.platform.name === Platforms.BROWSER) {
                        window.location.hash = '';
                    }

                    if (authResult && authResult.accessToken) {
                        this.authService.setAuth(authResult);
                        return new LoginSuccess();
                    } else {
                        debugger;
                        return new LoginFailure({ message: 'no accessToken', payload: authResult })
                    }
                }),
                catchError(error => of(new LoginFailure(error)))
            );
        })
    );
于 2020-02-04T06:25:59.627 回答