简体   繁体   English

Angular2 - 扩展路由器和Observable

[英]Angular2 - Extending router and Observable

In angular2 rc2 with the router module v 3.0.0.6alpha, I extend the RouterOulet to check if the user is logged in before accessing the admin. 在使用路由器模块v 3.0.0.6alpha的angular2 rc2中,我扩展了RouterOulet以检查用户是否在访问管理员之前已登录。 So this is the code : 所以这是代码:

@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() has to return a boolean. userService.isLoggedIn()必须返回一个布尔值。 My question is : How do I adapt my code to make an http call to check if the user is logged in ? 我的问题是:如何调整我的代码进行http调用以检查用户是否已登录? Because if the isLoggedIn method return an observable object, and I subscribe it, I can't return the result in the parent function. 因为如果isLoggedIn方法返回一个可观察对象,并且我订阅了它,我就无法在父函数中返回结果。

Please notice that the result of activate method of OutletRouter has changed. 请注意,OutletRouter的activate方法的结果已更改。

@angular/router-deprecated @角/路由器弃用

activate(nextInstruction: ComponentInstruction) : Promise<any>

@angular/router @角/路由器

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

which is not a Promise or Observable any more. 这不再是Promise或Observable。 New router implementation comes with a bit different solution that I think is cleaner: Guards. 新的路由器实现带来了一些我认为更清洁的解决方案:Guards。

A guard's return value controls the router's behavior: Guard的返回值控制路由器的行为:

if it returns true, the navigation process continues if it returns false, the navigation process stops and the user stays put The guard can also tell the router to navigate elsewhere, effectively canceling the current navigation. 如果它返回true,导航过程会继续,如果它返回false,导航过程停止并且用户保持放置警卫也可以告诉路由器在其他地方导航,有效地取消当前导航。

The guard might return its boolean answer synchronously. 警卫可能会同步返回其布尔答案。 But in many cases, the guard can't produce an answer synchronously. 但在许多情况下,警卫无法同步产生答案。 The guard could ask the user a question, save changes to the server, or fetch fresh data. 警卫可以向用户询问问题,保存对服务器的更改或获取新数据。 These are all asynchronous operations. 这些都是异步操作。

Accordingly, a routing guard can return an Observable and the router will wait for the observable to resolve to true or `false. 因此,路由保护可以返回Observable,路由器将等待observable解析为true或`false。

You can create auth.guard.ts: 您可以创建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();
  }
}

Now make sure your isLoggedIn return Observable (or Promise - try both as Angular2 Reference is not ready yet ). 现在确保你的isLoggedIn返回Observable(或Promise - 尝试两者,因为Angular2 Reference还没有准备好 )。 In my case API returns JSON in format: { success: true / false }. 在我的情况下,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;
        });
}

Then just modify your RouterConfig array: 然后只需修改您的RouterConfig数组:

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

Refer also to Angular2 Developer Guide 另请参阅Angular2开发人员指南

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

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