繁体   English   中英

Angular2 - 扩展路由器和Observable

[英]Angular2 - Extending router and Observable

在使用路由器模块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方法的结果已更改。

@角/路由器弃用

activate(nextInstruction: ComponentInstruction) : Promise<any>

@角/路由器

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

这不再是Promise或Observable。 新的路由器实现带来了一些我认为更清洁的解决方案:Guards。

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

如果它返回true,导航过程会继续,如果它返回false,导航过程停止并且用户保持放置警卫也可以告诉路由器在其他地方导航,有效地取消当前导航。

警卫可能会同步返回其布尔答案。 但在许多情况下,警卫无法同步产生答案。 警卫可以向用户询问问题,保存对服务器的更改或获取新数据。 这些都是异步操作。

因此,路由保护可以返回Observable,路由器将等待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开发人员指南

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM