2013-05-24 10 views
6

イベントハンドラ内でエラーが発生すると、コード実行が完全に停止して2番目のイベントコールバックが呼び出されません。例えばJavascriptエラーがコード実行を停止します

$(function() { 
    window.thisDoesntExist(); 
} 
$(function() { 
    //Do something unharmful and unrelated to the first event 
} 

あなたは簡単に両方の無名関数でのtry/catchを追加することによって、この(簡体字)の例では、問題を解決することができますが、実際には、これらの機能は、多くの場合、順番に他のいくつかのイベントハンドラを追加しますtry/catchが必要です。私はtry/catchブロックで詰め込まれた非常に反復的なコードで終わります。

私のプロジェクトは、各機能が異なるJSにある(ビルドプロセス中に連結される)モジュラー設計をしています。私は、エラーが他の機能のコード実行を停止しないように、各機能内のエラーを処理するためのより一般的な方法を探しています。

私はすでに次の解決策を試してみました: - window.onerror(あなたがこの機能にtrueを返す場合でも、コードの実行が停止している) - $(ウィンドウ).ERROR()=>非推奨となり、コードの実行が

+0

あなたは私の質問を読みましたか? この単純な例では、両方の匿名関数にtry/catchを追加することで簡単に問題を解決できますが、実際にはtry/catchが必要な他のイベントハンドラを追加することがあります。私はtry/catchブロックで詰め込まれた非常に反復的なコードで終わります。 – Webberig

+0

コードをできるだけ堅牢にしたい場合は、それは妥協点です。 – CBroe

+0

@Webberig、確かに私はそうです。必要な基本的な要件は、(任意の)エラーでコードを実行し続けることです。唯一の方法はtry catchを使うことです。それは最初のステップです。その後、エラーコールバックを使用するか、エラーイベントを発生させるか、エラー処理をしっかりと柔軟にすることができます。 Requirejsのソースコードを参照することもできますし、try catchも使用します。 https://github.com/jrburke/requirejs/blob/master/require.js –

答えて

-2

解決策が見つかりました。 setTimeoutを使用すると、コードは別のスレッドで実行されるため、Webページの他の部分は破られません。

$(function() { 
    setTimeout(function() { 
    window.thisDoesntExist(); 
    }, 0); 
}); 
$(function() { 
    setTimeout(function() { 
     //Do something unharmful and unrelated to the first event 
     alert("This passes") 
    }, 0); 
}); 

この例では、最初のエラーが発生した場合でも、2番目の関数が実行されます。一般的には(モジュールエラーを通じて静かにトラックへの道catchブロック、ないからhttp://jsfiddle.net/mathieumaes/uaEsy/

+1

+1があります。私は何かを学んだので、 -1これはスーパーグロスのハックです – mpd

+2

setTimoutの参照された関数は別のスレッドでは動作しません。 JavaScriptランタイムの実行スタックはシングルスレッドです。実際に起こっていることは、エラーがあなたのonerrorコールバックによって処理されたときに、実行スタックがクリアされていることです(エラーの後で追加のコードが実行されない理由です)。setTimeoutは、参照された関数をイベントキューに配置し、実行スタックがクリアされたときにそのキュー内のイベントを実行します。動作しますが、マルチスレッドのためではありません。 – user1739635

+0

さらに、asyncを実行しているときは順序が保証されていません。実装に依存します。これらのタスクを順番に実行する必要がある場合、競合条件が作成されます。私は文脈からここで問題はないと仮定しますが、一般的な解決策としては問題があります。 – guioconnor

5
を停止

ヘルパー関数を作成して、同じボイラープレートコードの重複を防ぐことができます。

function tryFunction(f, onerror) { 
    try { 
     if (typeof f == 'function') { 
      return f(); 
     } 
    } catch (e) { 
     return onerror(e); 
    } 
} 

$(function() { 
    var result = tryFunction(window.thisDoesNotExist, function (error) { 
     alert('Whoops: ' + error); 
    }); 
}); 

I created a little demonstration。それはやや異なっていますが、同じ考えです。

0

あなたは、単にmyFunction()

を呼び出す前if (typeof myFunction == 'function')を呼び出し、必要に応じて、あなたの関数が存在しない場合は、コンソールにエラーを記録する選択肢を持っているバートで言ったように、一般的な機能でそれをラップすることができます。

ウェブアプリケーションが多くのインタラクションとJSで膨大な場合、あまりにも多くのtry catchがアプリケーションのグローバルパフォーマンスを変更する可能性があります。

0

あなたが(下記参照、またはこのjsfiddle:http://jsfiddle.net/TVfCj/2/)のために、私は、tryキャッチを処理するラッパーで、このような何かをしようと扱う私は(実際にはない、としない)んだ道から

このと議論は、私がjsで始まっていることは明らかです。しかし、私はあなたがそのアイデアを得ることを願っています。そして、それは正しい/有用です。

var wrapper = { 
     wrap: function wrap(f) { 
      return function (args) { 
       try { 
        f.apply(null, args); 
       } catch (ex){ 
        console.log(f.name+" crashed with args "+args); 
       }; 
      }; 
     } 
    }; 

    var f1 = function f1Crashes(arg) { 
     return window.thisDoesntExist(); 
    }; 
    var f2 = function f2Crashes(arg) { 
     return window.thisDoesntExist(); 
    }; 

    var f3 = function f3MustNotCrash(arg) { 
     wrapper.wrap(f1)(arg); 
     wrapper.wrap(f2)(arg); 
    } 

    f3('myarg'); 
0

try - あなたは、あなたの質問にしようと言及catchパターンが正しい方法です - あなたはtryをしたい:ここ は、実施例です世界的に例外を処理し続けることには常に注意が必要です。その方法は、6ヵ月後にしか見つからないデータ破損のバグです。

あなたの本当の問題はこれです:

...現実には、これらの機能は、多くの場合、今度はのtry/catchを必要とする他のいくつかのイベントハンドラを追加します。私はtry/catchブロックで詰め込まれた非常に反復的なコードで終わります。

この修正はPromiseです。これは、ほとんどのブラウザではネイティブですが、イベントからの例外を除いて、イベントコールバックの両方を管理する標準的な方法を提供する、低速のもの(ahem、IE)で簡単にシームレスな新しい構造です。

Promiseを使用すると、コードでは常に解決策/成功または拒否/失敗のいずれかを行うことが約束されます。

function moduleA() { 
    return new Promise(function (resolve, reject) 
    { 
     try{ 
      var result = window.thisDoesntExist(); 
      resolve(resolve); // Success! 
     } 
     catch(err){ 
      reject(err); // Fail! 
     } 
    }); 
} 

ではなく、巣tryので、これは良いです - catchブロックごとでは、あなたができる代わりに、チェーンの約束コールバック:

moduleA(). 
    then(moduleB). 
    then(moduleC). 
    catch(errorHandler); // Catch any error from A, B, or C 

ます。また、エラーを処理し続けることができます:

moduleA(). 
    catch(continuableErrorHandler). // Catch any error from A 
    then(moduleB). 
    then(moduleC). 
    catch(errorHandler); // Catch any error from B or C 

をコールバックにはまだ多くのtrycatchブロックが必要ですが、0123でラップされたものは同じモジュラー方法で処理することができます。

JSの次に来るのはasyncawaitですが、今はトランスファーで使用することができます。これらの使用法は、読み易いコードを作ることを約束しています。最も重要なのは、Promiseチェーン全体から例外を集める上部にあるtry - catchです。

この回答はすでに長すぎますが、私はblogged about that in more detailです。

TL; DR:あなたの問題はある場合は、 "非常に反復[イベントコールバック]のtry/catchブロックを詰めコード"代わりPromiseを使用してみてください。

関連する問題