開発者ブログ
自習室 » hifiveにおける例外処理

hifiveにおける例外処理

Last modified by kashi on 2014/05/22, 10:49

例外処理

hifiveでは、例外が発生したときの処理を記述できる機構を用意しています。

commonFailHandler

h5.settings.commonFailHandler非同期処理が失敗した時に実行されます。デフォルトはnullで、関数を設定すると動作します。

ただし、非同期処理が失敗した時にfailハンドラが登録されていた場合は動作しません。非同期処理が失敗した時に動作するハンドラが登録されていない場合に、commonFailHandlerが『共通のfailハンドラ』として実行されます。

また、commonFailHandlerはh5.async.deferred()及びh5.ajax()などのhifiveのメソッドを利用した非同期処理が失敗した場合に呼ばれます。$.Defferd()$.ajax()を使用した場合はcommonFailHandlerは実行されません。

// commonFailHandlerの登録
h5.settings.commonFailHandler = function(){
   // 非同期処理の共通のfailハンドラとして動作する。
   // 引数及びthisは失敗した非同期処理のfailハンドラの引数及びthisになる
   console.log('commonFailHandler!');
}

// ----------------------
// h5.async.deferred()
// ----------------------
var dfd = h5.async.deferred();
dfd.reject(); // commonFailHandler!

var dfd2 = h5.async.deferred();
var promise2 = dfd2.promise();
promise2.fail(function(){
  // 登録されたfailハンドラ
});
dfd2.reject(); // failハンドラが登録されているのでcommonFailHandlerは実行されない

// ----------------------
// h5.ajax()
// ----------------------
h5.ajax('noExistPage'); // 'commonFailHandler!'

h5.ajax('noExistPage').fail(function(){});  // failハンドラが登録されているのでcommonFailHandlerは実行されない

h5.ajax('noExistPage', {
    error: function(){}
});
// errorによってエラー時のコールバックが登録されているのでcommonFailHandlerは実行されない

h5.ajax('noExistPage', {
    complete: function(){}
});
// completeによってエラー時のコールバックが登録されているのでcommonFailHandlerは実行されない

エラー時のコールバックが登録されていた場合にはcommonFailHandlerは実行されません。failメソッドに限らず、alwaysやthenでエラー時に動作するハンドラが登録されていた場合も、commonFailHandlerは動作しません。

var dfd3 = h5.async.deferred();
var promise3 = dfd3.promise();
promise3.always(function(){
  // alwaysを使ってdoneハンドラとfailハンドラを登録
});
dfd3.reject(); // failハンドラが登録されているのでcommonFailHandlerは実行されない

var dfd4 = h5.async.deferred();
var promise4 = dfd4.promise();
promise4.then(function(){
   // thenから登録したdoneハンドラ
}, function(){
   // thenから登録したfailハンドラ
});
dfd4.reject(); // failハンドラが登録されているのでcommonFailHandlerは実行されない

var dfd5 = h5.async.deferred();
var promise5 = dfd4.promise();
promise5.then(function(){ // 第2引数を省略してdoneハンドラだけ登録
   // thenから登録したdoneハンドラ
});
dfd4.reject(); // 'commonFailHandler!'

h5.async.when()を使用した時のcommonFailHandlerの動作

when()で実行した非同期処理に対してfailコールバックを指定していない場合で、when()に渡したいずれかのプロミスに基づく非同期処理が失敗したときは、when()による非同期処理についてのcommonFailHandlerが動作します。

when()の引数に渡した各プロミスに基づく非同期処理についてのcommonFailHandlerは動作はしません。

var dfd1 = h5.async.deferred();
var dfd2 = h5.async.deferred();
var dfd3 = h5.async.deferred();

var whenPromise = h5.async.when(dfd1.promise(), dfd2.promise(), dfd3.promise());

dfd1.reject();   // when()による非同期処理が失敗し、whenPromiseにfailハンドラが登録されていないので、commonFailHandlerが動作する

dfd2.reject();   // commonFailHandlerは動作しない
dfd3.reject();   // commonFailHandlerは動作しない

when()に対してfailハンドラを登録した場合はcommonFailHandlerは実行されません。

var dfd1 = h5.async.deferred();
var dfd2 = h5.async.deferred();
var dfd3 = h5.async.deferred();

var whenPromise = h5.async.when(dfd1.promise(), dfd2.promise(), dfd3.promise());
whenPromise.fail(function(){
    console.log('when fail');
});

dfd1.reject();   // 'when fail' commonFailHandlerは実行されない。
dfd2.reject();   // commonFailHandlerは実行されない。
dfd3.reject();   // commonFailHandlerは実行されない。

when()に渡されたプロミスは、失敗した時にwhen()のfailハンドラを呼ぶ、というエラー時の処理が追加されます。commonFailHandlerはfailハンドラが登録されていない(=エラー時に何もしない)非同期処理に対して動作するので、when()に渡されたプロミスについての非同期処理が失敗してもcommonFailHandlerは動作しません。

ただしwhen()自体が実行する非同期処理については、failハンドラを登録されていない場合にcommonFailHandlerが動作します。

errorInterceptor

アスペクトを利用して例外を処理する方法を紹介します。

hifiveでは、h5.core.interceptor.errorInterceptor「例外が発生するとcommonFailHandlerを実行するインターセプタ」を用意してあります。このインターセプタを使って、コントローラやロジックに対してアスペクトを掛けることで、commonFailHandlerで例外処理をすることができます。この方法は同期で例外が発生する場合に有効です。

// h5.jsを読み込むより先に実行してください
$(document).bind('h5preinit', function() {
   var aspects = [];
        aspects.push({
        target: '*',
        interceptors: h5.core.interceptor.errorInterceptor,
        pointCut: '*'
    });

    h5.settings.aspects = aspects;
});

アスペクトの掛け方についてはこちらをご覧ください。
チュートリアル(基本編) » 12.AOP(アスペクト)の適用

例外が発生すると、commonFailHandlerが実行されます。

h5.settings.commonFailHandler = function(e) {
    console.log(e.message);
}

h5.core.controller('body', {
    __name: 'SampleController',
    __init: function(){
       throw new Error('error interceptor test');  // commonFailHandlerにエラーオブジェクトが渡される
   }
});

errorInterceptorの詳細についてはAPIドキュメントをご覧ください。
JSDoc: h5.core.interceptor.errorInterceptor

window.onerror

window.onerrorはJavaScriptでエラーが起きた時に呼ばれるイベントです。window.onerrorに関数を登録すると、JavaScriptでエラーがあった時に関数が実行されます。tryブロックでエラーが発生した場合は実行されません。

※Android3以下、iOS4以下ではwindow.onerrorは動作しません。

window.onerror=function(errMsg, url, lineNumber) {
    console.log('window.onerror! ' + errMsg);
};

noexistfunc(); // window.onerror!  Uncaught ReferenceError: noexistfunc is not defined

try{
    noexistfunc(); // window.onerrorは実行されない
} catch(e){
}

同期、非同期に関わらず、try-catchで囲んでいない(想定していない)例外を全て処理したい場合に有用です。


Copyright (C) 2012-2017 NS Solutions Corporation, All Rights Reserved.