3

ルーター モジュール 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 メソッドが監視可能なオブジェクトを返し、それをサブスクライブすると、親関数で結果を返すことができないためです。

4

1 に答える 1

8

OutletRouter の activate メソッドの結果が変わっていることに注意してください。

@angular/router-非推奨

activate(nextInstruction: ComponentInstruction) : Promise<any>

@Angular/ルーター

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

これはもはや Promise または Observable ではありません。新しいルーターの実装には、私がよりクリーンだと思う少し異なるソリューションが付属しています: Guards.

ガードの戻り値は、ルーターの動作を制御します。

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 は { success: true / false } の形式で JSON を返します。

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 開発者ガイドも参照してください。

于 2016-06-17T19:43:57.183 に答える