Angular2-扩展路由器且可观察 [英] Angular2 - Extending router and Observable

查看:90
本文介绍了Angular2-扩展路由器且可观察的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

userService.isLoggedIn() has to return a boolean. My question is : How do I adapt my code to make an http call to check if the user is logged in ? Because if the isLoggedIn method return an observable object, and I subscribe it, I can't return the result in the parent function.

推荐答案

请注意,OutletRouter的activate方法的结果已更改.

Please notice that the result of activate method of OutletRouter has changed.

@不推荐使用角度/路由器

activate(nextInstruction: ComponentInstruction) : Promise<any>

@角度/路由器

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

不再是Promise或Observable.新的路由器实现带有一些我认为更干净的解决方案:警卫队.

which is not a Promise or Observable any more. New router implementation comes with a bit different solution that I think is cleaner: Guards.

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

A guard's return value controls the router's behavior:

如果返回true,则返回返回导航过程 否,导航过程停止并且用户停留在原处 还可以告诉路由器导航到其他地方,从而有效地取消 当前导航.

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.

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

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.

因此,路由防护可以返回Observable和 路由器将等待可观察对象解析为true或"false".

Accordingly, a routing guard can return an Observable and the router will wait for the observable to resolve to true or `false.

您可以创建auth.guard.ts:

You can create 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参考为尚未准备好).在我的情况下,API以以下格式返回JSON:{success:true/false}.

Now make sure your isLoggedIn return Observable (or Promise - try both as Angular2 Reference is not ready yet). In my case API returns JSON in format: { 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阵列:

Then just modify your RouterConfig array:

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

另请参阅 Angular2开发人员指南

这篇关于Angular2-扩展路由器且可观察的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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