2017-03-13 41 views
1

背景:
一個項目我的工作,我們已經使用AngularJS(1.6.2)使用JavaScript切換,以TypeScript 2.1.5。不能裝點AngularJS」的ExceptionHandler,作爲一個功能不承認爲

我們有一個裝飾器應用於$exceptionHandler服務,該服務會導致JavaScript異常對通用API進行調用,從而向開發團隊發送電子郵件;通過這種方式,我們可以輕鬆查看我們的終端用戶在野外遇到的前端錯誤。

問題:
我最近把這個裝飾器從JavaScript轉換成了TypeScript。當我嘗試運行該應用程序時,遇到無任何白屏。經過很多調試後,我發現這個問題是因爲AngularJS期望$provide.decorator傳遞一個函數以及一系列依賴關係。但是,一個對象正在被觀察,因此迫使Angular失效。

我通過在angular.js本身內部設置斷點來診斷問題;由於拋出的未處理的JavaScript異常,它特別會在4809行(函數createInternalInjector(cache, factory)內部)失敗,但實際負責失敗的部分是函數invoke(fn, self, locals, serviceName)內部的行4854。它失敗的原因是因爲依賴關係傳遞爲['$delegate', '$injector',];該設置中缺少該功能。

最後,我認爲要做的一件事就是在類代碼中定義一個JavaScript函數。這在我的情況下不起作用有兩個原因。首先,在我們的ts.config中,我們有noImplicitAny設置爲true;函數隱含的是any類型。此外,TypeScript本身似乎不會將function識別爲關鍵字,而是嘗試將其編譯爲類ExceptionHandler上的符號,但無法將其編譯。

打字稿異常處理程序:

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.以什麼方式我可以重寫打字稿異常處理程序正確由AngularJS拿起?
2.如果我不能,這是一個需要升級的AngularJS錯誤嗎?我知道一個事實,我不是唯一一個在TypeScript中使用AngularJS的人;由於語言選擇而無法裝飾服務似乎是一個相當大的問題。

+0

你爲什麼這樣做?將所有內容轉換爲類不是TS的目的。 'config'需要一個回調函數,而不是構造函數。 '$ exceptionHandler'是工廠函數,不是類。沒有上課的地方。 – estus

+0

我這樣做,因爲基於我對TypeScript的(有限)知識,它看起來像是正確的轉錄。如果不是,那麼我需要知道 - 我邀請您根據我的**問題**提供答案。 –

回答

1

將所有東西都轉換爲類不是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代碼失敗的原因是ExceptionHandler不與new調用,因此this不是一個對象,並且this.dispatchErrorEmail不是一個函數。

+0

這樣做。我不知道這些功能可以以類似的方式輸出。另外,我的背景是作爲一名C#程序員 - 我習慣於將東西放在課堂上。感謝您擴大我的視野。 –

+1

@AndrewGray不客氣。 ES6/TS類只是構造函數的語法糖。 A1並沒有用類來編寫,所以它大量使用工廠函數。但考慮使用「服務」服務和控制器的類。順便說一句,沒有真正的需要導出它們,它們可能只是匿名的箭頭函數。但出口他們好處測試一點。 – estus

+0

更進一步從這個答案,我做了一些關於我自己的代碼的研究。我的一些不好的假設是,'class'關鍵字映射到轉錄的JavaScript I中使用的IIFE模式;不是這種情況。相反,IIFE代替地(非常粗略地)對應於'命名空間'或'模塊'。 –