作为培训的一部分,我正在构建一个小型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函数迁移到服务并以与拦截器中相同的方式进行管道传输,我确实得到了预期的行为。只是在拦截器上不起作用。
答案 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()的成功回调中。