繁体   English   中英

无法使用TypeScript修饰AngularJS的ExceptionHandler,因为函数不被识别

[英]Cannot decorate AngularJS' ExceptionHandler using TypeScript, as a function isn't recognized as such

背景:
在我正在开发的项目中,我们已经从使用带有JavaScript的AngularJS(1.6.2)切换到TypeScript 2.1.5。

我们有一个应用于$exceptionHandler服务的装饰器,它导致JavaScript异常调用向开发团队发送电子邮件的公共API; 通过这种方式,我们可以很容易地看到最终用户在野外遇到的前端错误。

问题:
我最近将这个装饰器从JavaScript转换为TypeScript。 当我尝试运行应用程序时,我遇到了什么都没有的白屏。 经过大量调试后,我发现问题是因为AngularJS希望$provide.decorator传递一个函数以及一个依赖列表。 但是,正在观察一个对象,从而迫使Angular进行故障安全。

我通过在angular.js设置断点来诊断问题; 由于抛出的,未处理的JavaScript异常,它特别会在第4809行(在函数createInternalInjector(cache, factory) )失败,但是实际负责失败的部分是4854行,在函数invoke(fn, self, locals, serviceName)内部invoke(fn, self, locals, serviceName) 它失败的原因是因为传递的依赖关系是['$delegate', '$injector',] ; 该集合中缺少该功能。

最后,我考虑过的一件事就是在类代码中定义一个JavaScript函数。 由于两个原因,这在我的案例中不起作用。 首先,在我们的ts.config ,我们将noImplicitAny设置为true; 函数隐含在any类型中。 此外,TypeScript本身似乎不会将function识别为关键字,而是尝试将其编译为类ExceptionHandler上的符号。

TypeScript异常处理程序:

export class ExceptionHandler {
    public constructor(
        $provide: ng.auto.IProviderService
    ) {
        $provide.decorator('$exceptionHandler`, [
            '$delegate',
            '$injector',
            this.dispatchErrorEmail
        ]);
    }

    public dispatchErrorEmail(
        $delegate: ng.IExceptionHandlerService,
        $injector: ng.auto.IInjectorService
    ): (exception: any, cause: any) => void {
        return (exception: any, cause: any) => {
            // First, execute the default implementation.
            $delegate(exception, cause);

            // Get our Web Data Service, an $http wrapper, injected...
            let webDataSvc: WebDataSvc = $injector.get<WebDataSvc>('webDataSvc');

            // Tell the server to dispatch an email to the dev team.
            let args: Object = {
                'exception': exception
            };
            webDataSvc.get('/api/common/errorNotification', args);
        };
    }
}

angular.module('app').config(['$provide', ExceptionHandler]);

原JS:

(function () {
    'use strict';

    angular.module('app').config(['$provide', decorateExceptionHandler]);

    function decorateExceptionHandler($provide) {
        $provide.decorator('$exceptionHandler', ['$delegate', '$injector', dispatchErrorEmail]);
    }

    function dispatchErrorEmail($delegate, $injector) {
        return function (exception, cause) {
            // Execute default implementation.
            $delegate(exception, cause);

            var webDataSvc = $injector.get('webDataSvc');

            var args = {
                'exception': exception,
            };
            webDataSvc.get('/api/common/ErrorNotification', args);
        };
    }
})();

问题:
1.我可以用什么方式重写TypeScript异常处理程序,以便AngularJS正确选择?
2.如果我不能,这是一个需要升级的AngularJS错误吗? 我知道事实上我不是唯一一个使用TypeScript的AngularJS的人; 由于语言选择而无法装饰服务似乎是一个非常重要的问题。

将所有内容转换为类不是TS的目的,这里的类没有用处。 JS代码应该使用类型进行扩充,并且可能使用$inject注释进行增强。

angular.module('app').config(decorateExceptionHandler);

decorateExceptionHandler.$inject = ['$provide'];

export function decorateExceptionHandler($provide: ng.auto.IProviderService) {
    $provide.decorator('$exceptionHandler', dispatchErrorEmail);
}

dispatchErrorEmail.$inject = ['$delegate', '$injector'];

export function dispatchErrorEmail(
    $delegate: ng.IExceptionHandlerService,
    $injector: ng.auto.IInjectorService
): (exception: any, cause: any) => void { ... }

config需要常规函数,而不是构造函数。 原始TS代码失败的原因是没有使用new调用ExceptionHandler ,因此this不是对象,而this.dispatchErrorEmail不是函数。

这是使用TypeScript命名空间执行此操作的另一种方法。 对我来说感觉有点干净,保持异常扩展功能是孤立的,并且在概念上来自C#之类的东西。

exception.module.ts

import * as angular from 'angular';
import { LoggerModule } from '../logging/logger.module';
import { ExceptionExtension } from './exception.handler';

export const ExceptionModule = angular.module('app.common.exception', [LoggerModule])
    .config(ExceptionExtension.Configure)
    .name;

exception.handler.ts

import { ILoggerService } from '../logging/logger.service';

export namespace ExceptionExtension {
    export const ExtendExceptionHandler = ($delegate: ng.IExceptionHandlerService, logger: ILoggerService) => {
        return function (exception: Error, cause?: string): void {
            $delegate(exception, cause);
            logger.error(exception.message, "Uncaught Exception", cause ? cause : "");
        }
    };
    ExtendExceptionHandler.$inject = ['$delegate', 'ILoggerService'];

    export const Configure = ($provide: ng.auto.IProvideService) => {
        $provide.decorator('$exceptionHandler', ExtendExceptionHandler);
    };
    Configure.$inject = ['$provide'];
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM