Исключение Catch 401 в Angular2

#exception #angular #http-status-code-401

#исключение #angular #http-status-code-401

Вопрос:

Когда я пытаюсь подключиться к неавторизованному URL-адресу, я получаю в Chrome:

 zone.js:1274 POST http://localhost:8080/rest/v1/runs 401 (Unauthorized)
core.umd.js:3462 EXCEPTION: Response with status: 401 Unauthorized for URL: http://localhost:8080/rest/v1/runs
  

Код моего домашнего компонента:

 import {Component, OnInit} from '@angular/core';
import {Run} from "../_models/run";
import {Http, Response} from "@angular/http";
import {RunService} from "../_services/run.service";
import {Observable} from "rxjs";

@Component({
    moduleId: module.id,
    templateUrl: 'home.component.html'
})

export class HomeComponent implements OnInit{
    url: "http://localhost:8080/rest/v1/runs"
    username: string;
    runs: Run[];

    constructor(private http: Http, private runService: RunService) {

    }

    ngOnInit(): void {
        this.username = JSON.parse(localStorage.getItem("currentUser")).username;
        this.runService.getRuns()
            .subscribe(runs => {
                this.runs = runs;
            });
    }
}
  

И этот компонент использует эту службу:

 import { Injectable } from '@angular/core';
import {Http, Headers, Response, RequestOptions, URLSearchParams} from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map'
import {AuthenticationService} from "./authentication.service";
import {Run} from "../_models/run";

@Injectable()
export class RunService {
    url = "http://localhost:8080/rest/v1/runs";
    private token: string;

    constructor(private http: Http, private authenticationService: AuthenticationService) {

    }

    getRuns(): Observable<Run[]> {
        return this.http.post(this.url, JSON.stringify({ token: this.authenticationService.token }))
            .map((response: Response) => {
                console.log(response.status);
                if (response.status == 401) {
                    console.log("NOT AUTHORIZED");
                }

                let runs = response.json();
                console.log(runs);
                return runs;
            });
    }
}
  

Каков правильный способ поймать это исключение 401 и где я должен это сделать?
В компоненте или в службе? Конечная цель — перенаправить на страницу входа в систему, если произойдет какой-либо ответ 401.

Ответ №1:

Скорее всего, вы захотите выдать ошибку из своего RunService, которая может быть обнаружена в вашем компоненте, который может выполнять маршрутизацию на страницу входа в систему. Приведенный ниже код должен вам помочь:

В RunService:

Необходимо импортировать оператор catch из rxjs:

 import 'rxjs/add/operator/catch';
  

И ваша функция getRuns () должна измениться на

 getRuns(): Observable<Run[]> {
    return this.http.post(this.url, JSON.stringify({ token: this.authenticationService.token }))
        .map((response: Response) => {
            let runs = response.json();
            return runs;
        })
        .catch(e => {
            if (e.status === 401) {
                return Observable.throw('Unauthorized');
            }
            // do any other checking for statuses here
        });
  

и тогда ngOnInit в компоненте будет:

 ngOnInit(): void {
    this.username = JSON.parse(localStorage.getItem("currentUser")).username;
    this.runService.getRuns()
        .subscribe(runs => {
            this.runs = runs;
        }, (err) => {
            if (err === 'Unauthorized') { this.router.navigateByUrl('/login');
        });
}
  

Очевидно, что вы захотите адаптировать код к своим собственным потребностям и при необходимости изменить его, но процесс перехвата ошибки из Http, выдачи наблюдаемой ошибки и использования обратного вызова err для обработки ошибки в вашем компоненте должен решить вашу проблему.

Комментарии:

1. Спасибо, что все работает нормально, я поддержал ваш ответ и тоже отредактировал. еще раз огромное спасибо

2. Спасибо за это, возможно ли добавить службу, которая проверяет все остальные запросы и соответствующим образом перенаправляет вместо дублирования для каждого запроса

3. Да, вы могли бы это сделать — просто создайте службу, которая импортирует маршрутизатор, создайте функцию типа handleRequestErrors (err) и напишите там код для вашего пользовательского перенаправления. Затем, где бы вы ни захотели это сделать, вы можете вместо этого использовать сервис, что-то вроде (err) => { this.errorHandler.handleRequestErrors(err); }

4. @peppermcknight это должно быть включено в ваш ответ, поскольку важно избегать дублирования кода. Мне очень помогло! Спасибо

5. Я получаю status = 0 с 401, почему?