Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 下一个回调被中间调用_Angular_Rxjs_Ngrx - Fatal编程技术网

Angular 下一个回调被中间调用

Angular 下一个回调被中间调用,angular,rxjs,ngrx,Angular,Rxjs,Ngrx,我建立了一个商店界面: export interface IStore { user: IUser; } 其中,IUser是: export interface IUser { id: string; name: string; username: string; customer: string; } export function initialUserState(): IUser { return { id: '',

我建立了一个
商店
界面:

export interface IStore {
  user: IUser;
}
其中,
IUser
是:

export interface IUser {
    id: string;
    name: string;
    username: string;
    customer: string;
}
export function initialUserState(): IUser {
    return {
        id: '',
        name: '',
        username: '',
        customer: ''
    };
};
在我的组件中,我创建了对
IStore.user
的订阅:

export class LoginComponent implements OnInit {

    private user$: Observable<IUser>;
    private userSub: Subscription;

    constructor(private store$: Store<IStore>)
    {
        this.user$ = this.store$.select(state => state.user);
    }

    ngOnInit():void {
        this.userSub = this.user$.subscribe(
            (user: IUser) => {
                this.router.navigate(['/app']);  ((((1))))
            },
            (error: any) => {
                this.addAlert(error.message);
            }
        );
    }

    ngOnDestroy():void {
        this.userSub.unsubscribe();
    }

    public login():void {
        this.store$.dispatch({ type: 'USER_REDUCER_USER_LOGIN' });
    }
}
initialUserState()
是:

export interface IUser {
    id: string;
    name: string;
    username: string;
    customer: string;
}
export function initialUserState(): IUser {
    return {
        id: '',
        name: '',
        username: '',
        customer: ''
    };
};
有什么想法吗

编辑

@Injectable()
export class UserEffects {
  constructor(
    private _actions$: Actions,
    private _store$: Store<IStore>,
    private _userService: UsersService,
  ) { }

  @Effect({ dispatch: true }) userLogin$: Observable<Action> = this._actions$
    .ofType('USER_REDUCER_USER_LOGIN')
    .switchMap((action: Action) =>
      this._userService.checkPasswd(action.payload.username, action.payload.password)
        .map((user: any) => {
          return { type: 'USER_REDUCER_USER_LOGIN_SUCCESS', payload: user };
        })
        .catch((err) => {
          return Observable.of({
            type: 'USER_REDUCER_USER_LOGIN_ERROR',
            payload: { error: err }
          });
        })
    );
}
@Injectable()
导出类用户效果{
建造师(
私有_actions$:操作,
private _store$:商店,
私有用户服务:用户服务,
) { }
@Effect({dispatch:true})userLogin$:Observable=this.\u actions$
.of类型('USER\u REDUCER\u USER\u LOGIN')
.switchMap((操作:操作)=>
这是._userService.checkPasswd(action.payload.username,action.payload.password)
.map((用户:任意)=>{
返回{type:'USER\u REDUCER\u USER\u LOGIN\u SUCCESS',负载:USER};
})
.catch((错误)=>{
可观测收益({
键入:“用户\用户\登录\错误”,
有效负载:{error:err}
});
})
);
}

您看到的是预期的行为。当您订阅存储时,它会立即发出其当前状态,如果它尚未收到操作,则该状态将是初始状态

最简单的解决方案是使用
过滤器
操作符:

导入'rxjs/add/operator/filter';
ngOnInit():void{
this.userSub=this.user$
.filter(布尔值)
.订阅(
(用户:IUser)=>{this.router.navigate(['/app']);},
(错误:any)=>{this.addAlert(error.message);}
);
}
应用过滤器后,
user$
observable将不会发出空值,因此在用户登录之前不会进行导航

您可以使用
first
操作符进一步简化实现。当一个可观察到的完成或错误时,订阅者将自动取消订阅。通过使用
first
操作符,合成的可观测对象将在第一次发射后完成,因此无需手动取消接收,并且可以删除
userSub
属性和
ngondestory
方法:

导入'rxjs/add/operator/filter';
导入'rxjs/add/operator/first';
ngOnInit():void{
这个用户$
.filter(布尔值)
.first()
.订阅(
(用户:IUser)=>{this.router.navigate(['/app']);},
(错误:any)=>{this.addAlert(error.message);}
);
}
另一个解决方案是使用管理路由。您可能会决定
LoginComponent
的责任是获取凭据并对用户进行身份验证,但决定导航到哪里可能不是该组件的责任。如果您想让其他人负责导航,您可以创建一个路由效果,监听
USER\u REDUCER\u USER\u LOGIN\u SUCCESS


您可能还想考虑使用存储区中的路由器状态来促进时间旅行调试和撤销导航更改。有关更多信息,请参阅。

@非常感谢@cartant。事实上,我发现使用
@ngrx/effects
这种行为不会发生。我想知道为什么?我没有编辑任何代码,尽管添加了@Effect(见帖子)。。。