Angular2:当可观察订阅失败时如何重定向到登录页面?

时间:2017-08-17 09:32:37

标签: angular callback observable url-redirection canactivate

在文件 auth-guard-service.ts 中,为什么调用this.router.navigateByUrl('/ login')无法正常工作,同时警告消息打印?另一个文件( auth.service.ts )中的另一个调用正常工作。

AUTH-护service.ts

import { Injectable }          from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { Observable }          from 'rxjs';
import { Domain }              from 'domain';
import { AuthService }         from './auth.service';

@Injectable()
export class AuthGuardService implements CanActivate {
    private domain: Domain = new Domain();

    constructor(private router: Router) {}

    public canActivate(): Observable<boolean>|Promise<boolean>|boolean {
            return Observable.create(
                (observer) => {
                    this.domain.isauth()
                    .subscribe(
                        (res) => {
                            observer.next(true);
                        },
                        (err) => {
                            alert('You need to be authentificated to access this content');
                            // The call to navigateByUrl below does not work. To fix.
                            this.router.navigateByUrl('/login');
                        }
                    );
                }
            );
        }

auth.service.ts

import { Injectable }       from '@angular/core';
import { Router }           from '@angular/router';
import { Observable }       from 'rxjs';
import { Domain }           from 'domain';
import { ConfigService }    from './config.service';

@Injectable()
export class AuthService {
    private authObject: Observable<boolean>;
    private domain: Domain = new Domain();

    constructor(private router: Router) {}

    public login(login: string, password: string) : void {
        this.authObject = this.domain.auth(login, password);
        alert('Connecting... Please wait.');
        this.authObject.subscribe(
            (value) => {
                this.router.navigateByUrl('../view/dashboard');
            }
        );
    }

    public logout() : void {
        alert('Going to logout...');
        this.domain.logout();
        this.router.navigateByUrl('/login');
    }
}

app.routing.ts

import { ModuleWithProviders }  from '@angular/core';
import {
    Routes,
    RouterModule
}                               from '@angular/router';
import { LoginComponent }       from './login';
import {
    DashboardComponent,
    ViewComponent
}                               from './view';
import { AuthGuardService }     from './services';
const appRoutes: Routes = [
    {
        path: 'view',
        component: ViewComponent,
        canActivate: [AuthGuardService],
        children: [

            {
                path: 'dashboard',
                component: DashboardComponent
            }
            {
                path: '',
                redirectTo: 'dashboard',
                pathMatch: 'full'
            }
        ]
    },
    {
        path: 'login',
        component: LoginComponent
    }
    {
        path: '**',
        redirectTo: 'view'
    }
];

export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes, { useHash: true });

如果我收到错误(如果用户未连接),我只想重定向到登录页面。

配置:Angular2

3 个答案:

答案 0 :(得分:1)

  

angular documentation,&#34;始终指定完整   调用路由器的navigateByUrl方法时的绝对路径。&#34;

改为使用router.navigate

public canActivate(): Observable<boolean>|Promise<boolean>|boolean {
            return Observable.create(
                (observer) => {
                    this.domain.isauth()
                    .subscribe(
                        (res) => {
                            observer.next(true);
                        },
                        (err) => {
                            alert('You need to be authentificated to access this content');
                            // The call to navigateByUrl below does not work. To fix.
                            this.router.navigate(['/login']);
                        }
                    );
                }
            );
        }

答案 1 :(得分:0)

简短的解决方案(没有警报())是替换

this.router.navigate(['/login']);

通过

observer.next(this.router.navigate(['/login']));

或者,如果我想保留警告信息:

observer.next(false);
alert('You need to be authentificated to access this content');
this.router.navigateByUrl('/login');
  • 简短说明:

我们需要调用observer.next()来取消阻塞回调堆栈并执行下一个回调指令;

  • 更详细的解释:

1)如果你查看代码,我订阅了一个观察者。在我收到错误的情况下,没有执行下一个回调的指令,因此堆栈可能被“阻止”。

2)根据documentation navigateByUrl()是一个Promise,它通过回调工作。所以 navigateByUrl()可能需要先将观察者首先“解锁”,然后依次执行。

3)我们可能想知道为什么alert()在两条指令在同一块上时打印出错误消息没有任何问题。原因可能是因为Node在不同的队列中执行打印堆栈(alert(),console.log()等...)。

PS:我不是Angular2 / NodeJS / Callback / Promise / Observable的高手,所以我不确定答案。如果您有所了解,请随时回答。 :)

答案 2 :(得分:0)

这是我的答案。 subscription方法采用3个参数,下一个,错误和完成。订阅方法完成后重定向。在这种情况下,它将转到仪表板组件。

login() {
    this.authService.logIn(this.model).subscribe(
      next => {
        this.alertify.success('Logged in successfully');
      },
      error => {
        this.alertify.error(error);
      },
      () => {
        this.router.navigate(['/dashboard']);
      }
    );
  }
相关问题