角路由器防护和ROUTER_NAVIGATION效果顺序 [英] Angular router guard and ROUTER_NAVIGATION effect order

查看:111
本文介绍了角路由器防护和ROUTER_NAVIGATION效果顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个简单的(Angular 4)路由防护,它等待从后端加载一些数据:

There is a simple (Angular 4) route guard, which waits for some data to be loaded from backend:

@Injectable()
export class ContractsLoadedGuard implements CanActivate {
    constructor(private store: Store<State>) { }

    waitForData(): Observable<boolean> {
        return this.store.select(state => state.contracts)
            .map(contractList => !!contractList)
            .filter(loaded => loaded)
            .take(1);
    }

    canActivate(): Observable<boolean> { return this.waitForData(); }
}

路由:

const routes: Routes = [
    { path: 'app-list', canActivate: [ContractsLoadedGuard], component: AppListComponent },
];

最后是@ ngrx/router-store v4 ROUTER_NAVIGATION动作触发的@ ngrx/效果:

And finally there is an @ngrx/effects triggered by @ngrx/router-store v4 ROUTER_NAVIGATION action:

@Effect() routeChange$ = this.actions$
    .ofType(ROUTER_NAVIGATION)
    .filter((action: RouterNavigationAction) => action.payload.routerState.url.indexOf('/app-list') > -1)
    .withLatestFrom(this.store.select(state => state.contracts))
    .switchMap(([action, contracts]: ([RouterNavigationAction, ContractList])) =>
        this.restClient.load(action.payload.routerState.queryParams, contract));

不幸的是,当导航更改为/app-list时,首先执行ngrx效果(在保护之前),因此数据state.contracts尚不可用. 警卫尚未执行. 我确实必须添加.combineLatest() Rx运算符来等待有效的contracts数据(这是后卫的工作):

Unfortunatelly when navigation changes to /app-list the ngrx effect is executed first (before guard) and thus the data state.contracts are not available yet. The guard has not been executed yet. I do have to add .combineLatest() Rx operator to wait for the contracts data in effect also (this is guard's job):

@Effect() routeChange$ = this.actions$
    .ofType(ROUTER_NAVIGATION)
    .filter((action: RouterNavigationAction) => action.payload.routerState.url.indexOf('/app-list') > -1)
    .combineLatest(this.contractListGuard.waitForContractsToLoad(), a => a) <- HERE
    .withLatestFrom(this.store.select(state => state.contracts))
    .switchMap(/* same here */) 

我不确定这是否是一个好的解决方案.必须有更好的方法来做到这一点-不要复制有效的防护功能.

I'm not unsure if this is good solution enough. There must be a better way to do it - not duplicate the guard functionality in effect.

总结:在应用程序boostrap上,我需要从后端-contracts获取一些数据.如果用户导航到/app-list(立即重定向),则从服务器获取其他数据-基于某些查询参数和contracts-ngrx路由器ROUTER_NAVIGATION effect的执行顺序在警卫队执行顺序之前.如何正确处理呢?

To summarize: On application boostrap, I need to fetch some data from backend - contracts. If an user navigates to /app-list (immediate redirect) there are other data fetched from server - based on some query params and contracts - the ngrx router ROUTER_NAVIGATION effect execution order is before the guard execution order. How to handle this properly?

基于 GitHub-state_management_ngrx4

推荐答案

有一种方法可以实现它.您可以订阅Angular Router的ResolveEnd事件 https://angular.io/api/router/ResolveEnd生效,然后为RESOLVE_END分派您自己的操作,您可以在其中使用解析程序/保护数据进行处理.

There is one way to achieve it. You can subscribe to the Angular Router's ResolveEnd event https://angular.io/api/router/ResolveEnd in your effect and then dispatch your own action for RESOLVE_END where you can do stuff with your resolver / guard data.

实际上,我在ngrx/platform中创建了一个PR,其中ngrx/router会立即提供NAVIGATE_RESOLVE_END操作.我正在等待ngrx团队接受我的PR. https://github.com/ngrx/platform/pull/524/

Actually there is an PR in ngrx/platform that I created where ngrx/router will dispatch NAVIGATE_RESOLVE_END action out of the box. I am waiting for ngrx team to accept my PR. https://github.com/ngrx/platform/pull/524/

您可以订阅路由器事件并将其过滤为解析结束,然后调度自己的操作,称为Router_Resove_End操作等.

You can subscribe to router events and filter it for the Resolve End and dispatch your own action call it Router_Resove_End action etc.

this.router.events.filter(e => e instanceof ResolveEnd).subscribe(s => {
 // dispatch your own action here.
});

这篇关于角路由器防护和ROUTER_NAVIGATION效果顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆