LoginSignup
7
6

More than 5 years have passed since last update.

Angularでエラーハンドリングする2つの方法

Last updated at Posted at 2016-08-05

エラーハンドリングしよう!

はじめに

クライアント側(ブラウザ)で発生したエラー情報をWebサーバ側に渡してログ書いたり画面遷移させたり何らかの処理をさせたいときに、どうやったらエラー情報を取得できるか、またどうやったら独自処理を実装できるのか調べました。

※TypeScriptで実装しています。

$exceptionHandler

AngularJSでは例外が投げられた場合、$exceptionHandlerというサービスに処理が委譲され、$logサービスでブラウザコンソールにログが出力されます(※1)。

エラー処理を独自で実装したい場合の2つの方法です。

  • $exceptionHandlerを上書き(override)する方法
    • 公式サイトではこちらの例が紹介されています。
  • $exceptionHandlerを装飾(decorator)する方法
    • 海外のサイトではこちらが多い印象でした。

注意事項

  • 上書き(override)するともともと$exceptionHandlerがデフォルトで持っている処理(※1)が消えてしまうため、残したい場合は同等の処理を記述するか装飾(decorator)で対応する必要があります。

  • 公式サイトに書いてあるのですが、$exceptionHandlerはAngular監視外のエラーは検知できないようなので、try-catchでエラーを検知したりerrorオブジェクトを生成して自分でthrowする必要があります(⇒余談①:throw Error)。

実装方法

上書き(override)

公式

The example below will overwrite the default $exceptionHandler in order to (a) log uncaught errors to the backend for later inspection by the developers and (b) to use $log.warn() instead of $log.error().

overrideExample.js
angular.
  module('exceptionOverwrite', []).
  factory('$exceptionHandler', ['$log', 'logErrorsToBackend', function($log, logErrorsToBackend) {
    return function myExceptionHandler(exception, cause) {
      logErrorsToBackend(exception, cause);
      $log.warn(exception, cause);
    };
  }]);

引用元:AngularJS: API: $exceptionHandler

ちょっと内容が変わっていますがTypeScriptでシンプルにかくとこんな感じでしょうか。

overrideExample.ts
angular.
    module('exceptionOverwrite', []).
    factory('$exceptionHandler', () => {
        return (exception: Error, cause: string) => {
            //エラー発生時に実行したい処理
            alert(exception.message);//アラートで表示
            console.warn(exception.message);//コンソールで表示
        };
    })

buildinsiderのサイトでもサンプルを見ることができます。

装飾(decorator)

一例です。

decoratorExample.ts
angular.
    module('exceptionOverwrite', [])
    .config(['$provide', ($provide: ng.auto.IProvideService) => {
        $provide.decorator('$exceptionHandler',
            ['$delegate', extendExceptionHandler]);
    }]);

function extendExceptionHandler($delegate: ng.IExceptionHandlerService): ng.IExceptionHandlerService{
    return (exception: Error, cause: string) => {
        $delegate(exception, cause);
        //エラー発生時に実行したい処理
        alert(exception.message);//アラートで表示
        console.warn(exception.message);//コンソールで表示
    };
}

余談①:throw Error

任意の場所でエラーを発生させたいとき

error.ts
var error: Error = {
    name: "hogehoge",
    message: "エラーが発生しました。"
};
throw error;

余談②:Error: $injector:cdep

httpサービス使おうとしたときに循環参照発生したので回避策(extendExceptionHandler)

hoge.ts
function extendExceptionHandler($delegate: ng.IExceptionHandlerService): ng.IExceptionHandlerService{
    return (exception: Error, cause: string) => {
        $delegate(exception, cause);

        var $injector = angular.injector(['ng']);
        var $http:ng.IHttpService = $injector.get('$http');
        $http.post('hoge/hoge', exception);
    };
}

参考

AngularJS: API: $exceptionHandler
AngularJS Exception Logging Made Simple 
Github:exception-handler.provider.ts
stackoverflow:how-to-override-exceptionhandler-implementation

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6