Angular2 - 扩展路由器和 Observable

2023-11-29

在带有路由器模块 v 3.0.0.6alpha 的 angular2 rc2 中,我扩展了 RouterOulet 以在访问管理员之前检查用户是否已登录。这是代码:

@Directive({
    selector: 'router-outlet'
})

export class LoggedInRouterOutlet extends RouterOutlet 
{
    publicRoutes: Array<string>;
    private parentOutletMap: RouterOutletMap;
    private userService: UserService;
    private parentRouter: Router;

    constructor(
        parentOutletMap: RouterOutletMap,
        _location: ViewContainerRef,
        @Attribute('name') name: string,
        userService: UserService,
        parentRouter: Router
    ) { 
        super(parentOutletMap, _location, name);

        this.parentRouter = parentRouter;
        this.parentOutletMap = parentOutletMap;
        this.userService = userService;
        this.publicRoutes = [
            'public', 
            'login'
        ];
    }

    activate(factory: ComponentFactory<any>, activatedRoute: ActivatedRoute, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap) 
    {
        if (this._canActivate(factory.selector)) { 
            return super.activate(factory, activatedRoute, providers, outletMap); 
        }

        this.parentRouter.navigate(['/login']);
    }

    _canActivate(url) {
        return this.publicRoutes.indexOf(url) !== -1 || this.userService.isLoggedIn()
    }
}

userService.isLoggedIn() 必须返回一个布尔值。我的问题是:如何调整我的代码以进行 http 调用来检查用户是否登录?因为如果 isLoggedIn 方法返回一个可观察对象,并且我订阅了它,则无法在父函数中返回结果。


请注意OutletRouter的activate方法的结果已经改变。

@Angular/路由器已弃用

activate(nextInstruction: ComponentInstruction) : Promise<any>

@角度/路由器

activate(factory: ComponentFactory<any>, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap) : ComponentRef<any>

它不再是 Promise 或 Observable。新的路由器实现附带了一个有点不同的解决方案,我认为它更干净:Guards。

守卫的返回值控制路由器的行为:

如果返回true,则导航过程继续 false,导航过程停止并且用户保持原状 还可以告诉路由器导航到其他地方,有效地取消 当前导航。

警卫可能会同步返回其布尔答案。但在许多 在这种情况下,警卫无法同步给出答案。守卫 可以询问用户一个问题,将更改保存到服务器,或者获取 新鲜数据。这些都是异步操作。

因此,路由守卫可以返回一个 Observable,并且 路由器将等待可观察值解析为 true 或“false”。

您可以创建 auth.guard.ts:

import { Injectable }             from '@angular/core';
import { CanActivate,
         Router,
         ActivatedRouteSnapshot,
         RouterStateSnapshot }    from '@angular/router';
import { UserService }            from './user.service';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private userService: UserService, private router: Router) {}

  canActivate(
    // Not using but worth knowing about
    next:  ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ) {
    return this.userService.isLoggedIn();
  }
}

现在确保你的 isLoggedIn 返回 Observable (或 Promise - 尝试两者,因为 Angular2 Reference 是还没有准备好)。就我而言,API 返回 JSON 格式为:{ success: true / false }。

public isLoggedIn() : Observable<boolean> | boolean {
    let router: Router = this.router;
    let obs;

    try {
        obs = this.authHttp.get('/api/check/logged')
            .map(result => result.json())
            .map(resultJson => (resultJson && resultJson.success));

    } catch (err) {
        obs = Observable.of(false);
    }

    return obs
        .map(success => {
             // navigate to login page
             if (!success)
                 router.navigate(['/auth/login']);

             return success;
        });
}

然后只需修改您的 RouterConfig 数组:

{ path: '/secret', component: SercetComponent, canActivate: [AuthGuard] }

另请参阅Angular2 开发人员指南

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Angular2 - 扩展路由器和 Observable 的相关文章

随机推荐