angular - 根据显示的内容实现错误拦截器
问题描述
作为培训的一部分,我正在构建一个小型 Angular 应用程序。我正在尝试根据 Angular 教程中显示的内容实现错误拦截器。这个想法是我想处理错误,然后返回一个可观察的,以便我的组件仍然接收数据。
拦截器:
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 函数迁移到服务并以与拦截器中相同的方式对其进行管道传输。我确实得到了预期的行为。它只是在拦截器中不起作用。
解决方案
您可以将数据捕获为:
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)
}
});
}
推荐阅读
- laravel - 自定义刀片指令中的缓存问题 - Laravel
- pepper - Pepper Development 兼容性和版本
- javascript - 按文本选择链接(完全匹配)并替换 href
- vue.js - Vue Vuetify:无效的道具:道具“值”的自定义验证器检查失败。发现在--->
- javascript - 如何在 mapbox GL JS 上按日期范围过滤数据?
- python - 如何将嵌套字典的值分配给python中的单独变量?
- python - 编写递归函数来计算编号。图表
- python - 尝试在 Windows 10 中打开现有的命名管道 - errno 22,无效参数,但为什么呢?
- javascript - 按下按钮后如何使某些获取数据出现。使用 JavaScript 和 HTML
- android - GPS位置在本机反应中波动