我想将以下示例中显示的错误处理放到一个函数中:
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AuthService } from '../auth/auth.service';
import { tap, flatMap, concatMap } from 'rxjs/operators';
import { AlertController } from '@ionic/angular';
@Injectable()
export class ApiInterceptor implements HttpInterceptor {
constructor(private auth: AuthService, private alertCon: AlertController) { }
errorCodeToMessage = {
500: "Internal server error has occurred. Please contact support.",
404: "This resource can not be found. Please contact support.",
403: "Access denied. Are you logged in?"
};
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if(req.url != this.auth.LOGIN_URL && req.url != this.auth.REGISTRATION_URL)
return this.auth.getToken()
.pipe(
concatMap((token: string) => {
req = req.clone({
setHeaders: {
'authorization': token
}
});
// Also handle errors globally
return next.handle(req).pipe(
tap(x => x,
async (error) => {
const alert = await this.alertCon.create({
header: 'Error',
subHeader: null,
message: this.errorCodeToMessage[error.status],
buttons: ['OK']
});
await alert.present();
}
)
);
}))
;
else
return next.handle(req).pipe(
tap(x => x, async (error) => {
console.log("the error is: ");
console.log(error);
const alert = await this.alertCon.create({
header: 'Error',
subHeader: null,
message: this.errorCodeToMessage[error.status],
buttons: ['OK']
});
await alert.present();
})
);
}
}
但是,当我这样做时,注入的AlertController似乎不再可用。
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
import { AuthService } from '../auth/auth.service';
import { tap, flatMap, concatMap } from 'rxjs/operators';
import { AlertController } from '@ionic/angular';
@Injectable()
export class ApiInterceptor implements HttpInterceptor {
constructor(private auth: AuthService, private alertCon: AlertController) { }
errorCodeToMessage = {
500: "Internal server error has occurred. Please contact support.",
404: "This resource can not be found. Please contact support.",
403: "Access denied. Are you logged in?"
};
async handleError(error) {
console.log(error);
const alert = await this.alertCon.create({
header: 'Error',
subHeader: null,
message: this.errorCodeToMessage[error.status],
buttons: ['OK']
});
await alert.present();
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if(req.url != this.auth.LOGIN_URL && req.url != this.auth.REGISTRATION_URL)
return this.auth.getToken()
.pipe(
concatMap((token: string) => {
req = req.clone({
setHeaders: {
'authorization': token
}
});
// Also handle errors globally
return next.handle(req).pipe(
tap(x => x, this.handleError)
);
}))
;
else
return next.handle(req).pipe(
tap(x => x, this.handleError)
);
}
}
运行时错误:
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'create' of undefined
TypeError: Cannot read property 'create' of undefined
at TapSubscriber.<anonymous> (api.interceptor.ts:23)
at step (tslib.es6.js:97)
at Object.next (tslib.es6.js:78)
at tslib.es6.js:71
at new ZoneAwarePromise (zone.js:910)
at Module.__awaiter (tslib.es6.js:67)
at TapSubscriber.push../src/app/api/api.interceptor.ts.ApiInterceptor.handleError [as _tapError] (api.interceptor.ts:21)
at TapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._error (tap.js:55)
at TapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:60)
at XMLHttpRequest.onLoad (http.js:1640)
at resolvePromise (zone.js:831)
at new ZoneAwarePromise (zone.js:913)
at Module.__awaiter (tslib.es6.js:67)
at TapSubscriber.push../src/app/api/api.interceptor.ts.ApiInterceptor.handleError [as _tapError] (api.interceptor.ts:21)
at TapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._error (tap.js:55)
at TapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:60)
at XMLHttpRequest.onLoad (http.js:1640)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17290)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
我猜测这与不在闭包中有关,但我可能是错的。为什么会发生这种情况?我该怎么办才能让一个函数执行错误处理?
答案 0 :(得分:2)
如果使errorHandler成为箭头函数,则它应该包装this
上下文,并允许您在拦截方法内部访问注入的AlertController。
handleError = async (error: any) => {
console.log(error);
const alert = await this.alertCon.create({
header: 'Error',
subHeader: null,
message: this.errorCodeToMessage[error.status],
buttons: ['OK']
});
await alert.present();
}
答案 1 :(得分:1)
您可以使用全局错误处理程序
首先,让我们定义一个将从
继承的GlobalErrorHandler类。Kotlin
现在在我们的模块中,我们必须告诉Angular使用我们的import { ErrorHandler, Injectable} from '@angular/core';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
constructor() { }
handleError(error) {
console.log('Error Occured')
// IMPORTANT: Rethrow the error otherwise it gets swallowed
throw error;
}
}
而不是像下面这样的默认值:
GlobalErrorHandler
答案 2 :(得分:0)
在代码中进行更改。
不可变逻辑,用于更新请求标头。使用相同的逻辑 也更新参数。
而不是tap运算符,请使用catchError运算符。
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (
req.url !== this.auth.LOGIN_URL &&
req.url !== this.auth.REGISTRATION_URL
) {
return this.auth.getToken().pipe(
concatMap((token: string) => {
const updatedReq = req.clone({
headers: req.headers.set('authorization', token)
});
// Also handle errors globally
return next.handle(updatedReq).pipe(catchError(this.handleError));
})
);
} else {
return next.handle(req).pipe(catchError(this.handleError));
}
}
handleError(err): Observable<any> {
// error logs updation logics here.
return throwError(err);
}