根据显示的内容实施错误拦截器

时间:2018-08-07 16:39:25

标签: angular typescript rxjs observable

作为培训的一部分,我正在构建一个小型Angular应用程序。我正在尝试根据Angular教程中显示的内容实现错误拦截器。我的想法是,我想处理该错误,然后返回一个observable,以便我的组件仍可以接收数据。

拦截器:

    import { Injectable } from '@angular/core';
import {
    HttpRequest,
    HttpHandler,
    HttpEvent,
    HttpInterceptor
} from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ToastrService } from 'ngx-toastr';

@Injectable({
    providedIn: 'root'
})
export class ErrorInterceptor implements HttpInterceptor {

    constructor(private toastr: ToastrService) { }

    private handleError<T> (result?: T) {
        return (error: any): Observable<T> => {      
          // Log the error on the console.
          console.log(error);    
          // Display user friendly message.
          this.toastr.error(`${error.error.message}`, `${error.statusText}:`);      
          // Let the app keep running by returning an empty result.
          console.log(result);
          return of(result as T);
        };
    }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next
            .handle(request)
            .pipe(
                catchError(this.handleError<any>({data: {token: 'asd'}}))
            );
    }
}

服务:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { Subscription, Observable, of, throwError } from 'rxjs';
import { tap, map, catchError } from 'rxjs/operators';

import { LoginInput } from '../models/login.input-model';
import { RegisterInput } from '../models/register.input-model';
import { ServerResponse } from '../../../core/models/server-response.model';
import { ToastrService } from 'ngx-toastr';

const root = '/api/';

@Injectable({
providedIn: 'root'
})
export class AuthService {
    private loginUrl: string = root + 'auth/login';
    private registerUrl: string = root + 'auth/signup';
    private login$: Subscription;
    private register$: Subscription;

constructor(
    private http: HttpClient,
    private router: Router,
    private toastr: ToastrService) { }


private saveToken(data) {
    localStorage.setItem('token', data.token);
}

login(payload: LoginInput): void {
    this.login$ = this.http
        .post<ServerResponse>(this.loginUrl, payload)
        .subscribe((loginData) => {
            console.log('loginData: ' + loginData);
            // this.router.navigate(['/home']);
        });
}

clearLoginSubscription() {
    if (this.login$) this.login$.unsubscribe();
}    

}

预期的行为:拦截器处理错误并以可观察的方式返回结果。然后在订阅时发出数据。 实际行为:拦截器处理该错误,并且没有其他任何反应。登录/注册订阅时不会发送任何数据。

注意:我发现,如果我将handleError函数迁移到服务并以与拦截器中相同的方式进行管道传输,我确实得到了预期的行为。只是在拦截器上不起作用。

2 个答案:

答案 0 :(得分:1)

您可以按以下方式捕获数据:

this.http
        .post<ServerResponse>(this.loginUrl, payload)
        .subscribe((loginData) => {
            console.log('loginData: ' + loginData);
            // this.router.navigate(['/home']);
        }, (err: HttpErrorReponse) => {
          console.log(err);
        };

http-intercepter.ts

    /**
     * 
     * @param req - parameter to handle http request
     * @param next - parameter for http handler
     */
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const started = Date.now();
        /**
         * Handle newly created request with updated header (if given)
         */
        return next.handle(req).do((event: HttpEvent<any>) => {
            /**
             * Sucessfull Http Response Time.
             */
            if (event instanceof HttpResponse) {
                const elapsed = Date.now() - started;
            }

        }, (err: any) => {
            /**
             * redirect to the error_handler route according to error status or error_code
             * or show a modal
             */
            if (err instanceof HttpErrorResponse) {
                console.log(err)
            }
        });
    }

答案 1 :(得分:0)

对于那些想要处理错误然后再进行错误处理的人,只需实施追赶和扔掉策略

您的handleError函数必须抛出错误:

return throwError(result);

这样,您的组件可以接收数据,但是可以在错误回调中,而不是在subscribe()的成功回调中。

参考:https://blog.angular-university.io/rxjs-error-handling/