本文介绍了自定义错误处理程序抛出错误:无法读取未定义的属性"get"(注入器)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用角度4构建自定义错误处理程序,以使用错误拦截器处理不同类型的应用程序错误

I am building a custom error handler in angular 4 to handle different kind of application error with error interceptor

创建一个基类( app-error.ts )和其他类(例如,处理403错误创建类 access-denied.ts ),以扩展此基础基类.

create a base class( app-error.ts ) and other classes ( for eg. to handle 403 errors create class access-denied.ts ) which extend this base class.

在基类中注入了服务toastrService,我想显示子类的自定义消息,但会在

in the base class have injected a service toastrService and I want to display custom message from the child class BUT it gives the error on

无法读取未定义的属性'get'

Cannot read property 'get' of undefined

此问题与OOPS概念有关.我不明白如何获取重写父方法或使用自定义参数调用.

thisissue is related to OOPS concept. I do not understand how to get override parent method or call with my custom argument.

TS v 2.3.3角度v 4.3.4

TS v 2.3.3angular v 4.3.4

providers: [
{ provide: ErrorHandler, useClass: AppErrorHandler }
]

注意:AppErrorHandler类与AppError完全不同,后者扩展了处理系统错误的角度ErorHandler接口.

NOTE: AppErrorHandler class is completely different than AppError which extend angular ErorHandler interface which handle system errors.

import { Router } from '@angular/router';
import { Injectable, Injector } from '@angular/core';
import { HttpInterceptor, HttpResponse, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';

import {
    AuthFail,
    BadInput,
    NotFoundError,
    ServerError,
    AppError,
    AccessDenied,
} from '../shared/errors';
import { AuthenticationService } from './../authentication/authentication.service';


@Injectable()
export class ErrorInterceptor implements HttpInterceptor {

    private auth: AuthenticationService;
    constructor(private router: Router, private injector: Injector) { }
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const auth = this.injector.get(AuthenticationService);
        return next.handle(req).catch((err: HttpErrorResponse) => {
            if (err instanceof HttpErrorResponse) {
                if (err.status === 401) {
                    return Observable.throw(new AuthFail(err.error));
                }
                if (err.status === 400) {
                    return Observable.throw(new BadInput(err.error));
                }
                if (err.status === 404) {
                    return Observable.throw(new NotFoundError());
                }
                if (err.status === 403) {
                    return Observable.throw(new AccessDenied());
                }
                return Observable.throw(new AppError(err));
            }
        });
    }
}

access-denied.ts

import { AppError } from './app-error';
export class AccessDenied extends AppError {
    constructor(public originalError?: any) {
        super();
        console.log('inside acces denied constructor');
        // super.handleError("superrrrr"); // this also doesn't work
    }

    public handleError(): void {
        console.log('handleError: ', );
        super.handleError("Access denined error occured");
    }
}

app-error.ts

import { Inject, Injector } from "@angular/core";

import { ToastrService } from "ngx-toastr";

export class AppError {
    toastrService: ToastrService;
    constructor(public originalError?: any, private injector?: Injector) {
        this.toastrService = this.injector.get(ToastrService);
    }

    // NOTE: using getter seems impossible to access in child so add the same in constructor
    // get toastrService(): ToastrService {
    //  return this.injector.get(ToastrService);
    // }

    public handleError(msg: string): void {
        this.toastrService.error(`Error Message: ${msg}`,
            "Error", {
                closeButton: true,
                timeOut: 5000,
                onActivateTick: true
            }
        );
    }

}

给出错误

core.es5.js:1020 ERROR TypeError: Cannot read property 'get' of undefined
    at AccessDenied.AppError (app-error.ts:8)
    at new AccessDenied (access-denied.ts:6)
    at CatchSubscriber.eval [as selector] (error.interceptor.ts:61)
    at CatchSubscriber.error (catchError.js:105)
    at XMLHttpRequest.onLoad (http.es5.js:1739)
    at ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.es5.js:3881)
    at ZoneDelegate.invokeTask (zone.js:420)
    at Zone.runTask (zone.js:188)
    at ZoneTask.invokeTask [as invoke] (zone.js:496)

推荐答案

AccessDenied错误地扩展了AppError. super()导致未定义injector,并且injectorAppError构造函数中不应是可选的,因为它是必需的.

AccessDenied incorrectly extends AppError. super() results in injector being undefined, and injector shouldn't be optional in AppError constructor, because it is required.

可以通过强制设置参数来解决:

It could be fixed by making a parameter obligatory:

constructor(private injector: Injector, public originalError?: any) {
    this.toastrService = this.injector.get(ToastrService);
}

AccessDenied中可以省略构造函数.并且应该像new AccessDenied(injector)一样被实例化.

The constructor can be omitted in AccessDenied. And should be instantiated like new AccessDenied(injector).

这里真正的问题是AppError会完成本不应该做的工作.考虑到它只包含以后可以使用err instanceof AppError确定的错误,因此它不应该具有handleError中当前发生的副作用.

The real problem here is that AppError does the work it isn't supposed to to. Considering that it just contains the error that can be later determined with err instanceof AppError, it shouldn't do side effects that are currently done in handleError.

handleError中的逻辑可以移到ToastrService中的方法或接受AppError实例的单独的错误服务中.如果需要为错误类型(例如Access denied error occurred)提供默认消息,则AppError可以具有包含消息的公共属性.

The logic in handleError could be moved to a method in ToastrService or separate error service that accepts an instance of AppError. If there's a need to provide default message for error type like Access denied error occurred, AppError can have public property that contains the message.

这篇关于自定义错误处理程序抛出错误:无法读取未定义的属性"get"(注入器)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 10:37