Angular 4: невозможно перенаправить изнутри подписки

После ряда неудачных попыток я все еще не могу перенаправить изнутри подписки.

Я хочу поймать код ошибки 401, чтобы перенаправить пользователя на страницу входа, поэтому в http.get.subscribe, если у меня есть ошибка, и если это 401, я выполняю goLogin(). Эта функция должна указать маршрутизатору перейти на страницу входа в систему, но это не так. Все работает, кроме маршрутизации.

Вот мой код:

import { Http } from '@angular/http';
import { Injectable, NgZone } from '@angular/core';

import { CategoryFactory } from  "./../factory/category.factory";
import { StatusFactory } from  "./../factory/status.factory";
import { TicketFactory } from  "./../factory/ticket.factory";

import { HeaderProvider } from  "./../provider/header.provider";

import { Router, ActivatedRoute } from '@angular/router';

@Injectable()
export class TicketService {

    public liste: TicketFactory[] = [];

    constructor(private http: Http, private requestoptions:HeaderProvider, private _router:Router, private r:ActivatedRoute, private zone: NgZone) {

        this.http.get('/issue', this.requestoptions.options)
        .map(
            res => res.json(),
            err => err.json()
        )
        .subscribe(
            (liste:any) => {
                liste.forEach((l) => {
                    let t = new TicketFactory(
                        l.id,
                        l.title,
                        l.author,
                        l.text,
                        l.email,
                        new CategoryFactory(l.category.id, l.category.label),
                        new StatusFactory(l.status.id, l.status.label),
                        l.createdat,
                        l.priority,
                        l.sendto
                    );

                    this.liste.push(t);
                })
            },
            (err:any) => {
                if(err.json().code === 401) {
                    this.goLogin();
                }
            },
        )
    }

    goLogin = (): void  => {

        this.zone.run(() => { console.log('go login'); this._router.navigate(['login']) })
    }

    getList = () : TicketFactory[] => {
        return this.liste;
    }

    getTicket = (idticket):any => {
        return this.http.get('/issue/' + idticket, this.requestoptions.options).map(res => res.json());
    }

    deleteTicket = (idticket):any => {
        return this.http.delete('/issue/' + idticket, this.requestoptions.options)
            .toPromise()
            .then()
            .catch();
    }
}

Вот app.routes.ts

import { Routes }                       from '@angular/router';

import { FormComponent }                from './components/form/form.component';
import { LoginComponent }               from './components/login/login.component';
import { SigninComponent }              from './components/signin/signin.component';
import { TicketComponent }              from './components/ticket/ticket.component';
import { TicketListComponent }          from './components/ticketslist/ticketlist.component';

import { OnlyLoggedInUsersGuard }       from './components/guard/guard.component';

export const appRoutes: Routes = [
    {
        path: 'signin',
        component: SigninComponent,
        canActivate: [OnlyLoggedInUsersGuard]
    },
    {
        path: 'tickets/:id',
        component: TicketComponent,
        canActivate: [OnlyLoggedInUsersGuard]
    },
    {
        path: 'tickets',
        component: TicketListComponent,
        canActivate: [OnlyLoggedInUsersGuard]
    },
    {
        path: 'login',
        component: LoginComponent
    },
    {
        path: '',
        component: FormComponent
    },
    {
        path: '**',
        redirectTo: ''
    }
]

Он переходит в goLogin(); и console.log(...) выполняется, но не перенаправляет на страницу входа.

Вот вывод консоли, если это может помочь:

14:36:07.962 zone.js:2263 GET http://localhost:4200/user 401 (Unauthorized)
14:36:08.036 core.es5.js:1020 ERROR Response {_body: "{"code":401,"message":"Invalid authentication token"}", status: 401, ok: false, statusText: "Unauthorized", headers: Headers…}
14:36:08.048 zone.js:2263 GET http://localhost:4200/category 401 (Unauthorized)
14:36:08.110 core.es5.js:1020 ERROR Response {_body: "{"code":401,"message":"Invalid authentication token"}", status: 401, ok: false, statusText: "Unauthorized", headers: Headers…}
14:36:08.116 zone.js:2263 GET http://localhost:4200/issue 401 (Unauthorized)
14:36:08.122 ticket.service.ts:53 go login
14:36:08.479 zone.js:2263 GET http://localhost:4200/status 401 (Unauthorized)
14:36:08.575 core.es5.js:1020 ERROR Response {_body: "{"code":401,"message":"Invalid authentication token"}", status: 401, ok: false, statusText: "Unauthorized", headers: Headers…}

person Stéphane Helbling    schedule 21.06.2017    source источник
comment
ошибки в консоли?   -  person Vivek Doshi    schedule 21.06.2017
comment
Кажется правильным, вы пытались поставить «/» перед «логином»?   -  person omerv2    schedule 21.06.2017
comment
.map(res => res.json(), err => err.json()) ? Вы пытались зарегистрировать ошибку в обработчике ошибок?   -  person smnbbrv    schedule 21.06.2017
comment
Ошибок в консоли нет. С '/' ничего не меняется. Я пробовал, но мне не помогло.   -  person Stéphane Helbling    schedule 21.06.2017
comment
не могли бы вы также опубликовать route.ts ?   -  person Vivek Doshi    schedule 21.06.2017
comment
Я отредактировал свой пост, чтобы добавить его.   -  person Stéphane Helbling    schedule 21.06.2017
comment
Вы пытались использовать оператор catch (с get) для отлова ошибок?   -  person Rob Zuber    schedule 21.06.2017
comment
catch() недоступен для Observable, а только для Promise   -  person Stéphane Helbling    schedule 21.06.2017
comment
Я что-то упускаю? Улов недоступен для типа наблюдаемых в Angular? xgrommx.github.io/rx-book/content/observable/   -  person Rob Zuber    schedule 21.06.2017
comment
Я предполагаю, что он перенаправляет вас на логин, но затем снова проверяет авторизацию! ты не думаешь. Как я вижу из ваших логов.   -  person Yordan Nikolov    schedule 21.06.2017
comment
Меня не перенаправляет. Он продолжает делать запросы к серверной части. Он должен остановиться после this.list = listtickets.getList(); в this.listCategory = listcategory.getList(); this.listStatus = liststatus.getList(); this.listSendTo = listUser.getList();, но это не так.   -  person Stéphane Helbling    schedule 21.06.2017
comment
Попробуйте создать новое свойство в своем классе, например private auth = false;, затем используйте оператор takeWhile после карты .takeWhile(() => !this.auth), затем при ошибке установите this.auth = true и поместите this._router.navigate(['login']) как полный cb подписчика в качестве третьего параметра.   -  person Yordan Nikolov    schedule 21.06.2017
comment
Я только что попробовал, но это кажется неправильным. Проверьте мой ответ с кодом ниже, чтобы сказать мне, если я сделал неправильно.   -  person Stéphane Helbling    schedule 21.06.2017


Ответы (2)


Вы должны удалить this.zone.run(...), так как это не требуется. Приложение должно оставаться в угловой области. Вам также понадобится / перед маршрутом.

Попробуйте поменять местами:

goLogin = (): void  => {
    this.zone.run(() => { console.log('go login'); this._router.navigate(['login']) })
}

к следующему:

goLogin = (): void  => {
    console.log('go login');
    this._router.navigate(['/login']) })
}
person mast3rd3mon    schedule 26.09.2017

person    schedule
comment
С this._router.navigateByUrl('login') он по-прежнему ничего не делает. - person Stéphane Helbling; 21.06.2017
comment
this.router.navigateByUrl('/логин'); - person Mahesh Bhattarai; 21.06.2017
comment
Хотя этот код может дать ответ на вопрос, предоставление дополнительного контекста относительно того, как и/или почему он решает проблему, улучшит долгосрочную ценность ответа. - person Badacadabra; 21.06.2017