JavaScriptエラー処理のベストプラクティスは何ですか?


137

私はJavaScriptをもう少しエラープルーフを作り始めるために探している、と私は使用上の文書の多くを見つけることだtrycatchfinally、とthrow、私は、どこでエラーをスローするように専門家からの助言のトンを見つけることありませんよ。

  • すべてのコードをtry / catchでラップする必要がありますか?
  • エラーをキャッチする必要がある時点このようなアドバイスはありますか?
  • 本番環境でコードを静かに失敗させるのではなく、エラーを発生させることの欠点はありますか?
  • これは実装に関してSOで触れられてきましたが、サーバーログJSエラーは効果的な戦略ですか?
  • アプリケーションのトラップエラーに関して、他に知っておくべきことはありますか?

私はまた、エラー処理についてのすばらしい章や詳細な説明がある本を聞くための完全なゲームです。雄弁なJavaScriptはこの問題に触れていますが、この問題についてはあまり規範的ではなく、意見もありません。

あなたが与えることができるアドバイスをありがとう!


それは確かに何かがうまくいかなかった場合にどれほど壮大に失敗するか、そして起こり得るエラーメッセージの量に依存します。エラーログディレクトリがいっぱいになっているため、失敗したくないですか。-ここで見ましたか。stackoverflow.com/search?q=error+logging+javascript
mplungjan

@mplungjan-私はそこの答えをスキャンしましたが、あまり標準的ではないようで、Javascriptエラー処理/例外のベストプラクティスを検索しても何も見つかりませんでした。自分の理解と将来のサーチャー。おそらく、これはベストプラクティスを処方することができないトピックですが、それぞれの状況は非常にユニークです。
Joshua Cody

1
「すべてのコードをtry / catchでラップする必要がありますか?」もちろん違います。常に機能することがわかっているコードはたくさんあります(もちろん、テストすることを前提としていますが、try / catchの目的は、コーディングエラーをキャッチしたりつぶしたりすることではありません)。通常はリソースアクセスなど、制御できない何かが原因で時々失敗する可能性のあるコードのみをラップします。注:失敗する可能性のあるものには、エラー処理が組み込まれています。たとえば、Ajaxを最初からコーディングする必要がない場合ブラウザー間の問題を処理し、エラーハンドラー関数を指定できるライブラリーはたくさんあります。
nnnnnn 2011年

1
これは良い質問です、ジョシュ、+ 1。多くの構文アドバイスがありますが、あなたが言うように、それは簡単な部分です。この質問の回答(stackoverflow.com/questions/2825427/…)では、例外がJSで一般的に使用されておらず、理由が示されていると説明されています。
ホイットニーランド、2011

回答:


63

エンタープライズJavaScriptエラー処理に関する非常に興味深いスライドのセットは、http://www.devhands.com/2008/10/javascript-error-handling-and-general-best-practices/にあります。

要約すると:

  1. コードが失敗すると仮定する
  2. エラーをサーバーに記録する
  3. ブラウザではなくあなたがエラーを処理する
  4. エラーが発生する可能性のある場所を特定する
  5. 自分のエラーを投げる
  6. 致命的なエラーと致命的でないエラーを区別する
  7. デバッグモードを提供する

スライドはより詳細に進んでおり、おそらく方向性を示すでしょう。

更新

上記のプレゼンテーションはここにあります:http : //www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation


24
devhandsリンクが壊れています。
ライアンゲイツ

7
2017年にこれを読んだ人には、スライドからあまり価値がないと私は主張します。この要約は情報の90%を提供します。それはまだ貴重な情報です。乾杯!
フィリップヘベール

29

Yahoo!のニコラス・ザカス 名声は、Ajax Experience 2008でエンタープライズエラー処理(スライド)に関する講演を行いました。

function log(sev,msg) {
    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

// usage
log(1, "Something bad happened.")

// Auto-log uncaught JS errors
window.onerror = function(msg, url, line) {
    log(1, msg);
    return true;
}

1年後、Nicholas Zakasがブログにアップデートを投稿しました。これには、(アスペクト指向プログラミングを使用して)プロダクション環境にエラー処理コードを自動的に挿入する巧妙なパターンが含まれています。

window.error呼び出しのロギングを開始すると、2つのことに気づくでしょう。

  1. サイトがかなり複雑な場合、多くのエラーが記録されます
  2. 役に立たない "window.error in undefined:0"メッセージがたくさん表示されます

ログエントリの急流を減らすのは、サーバーにログを記録する前に重大度や乱数をテストするのと同じくらい簡単です。

function log(sev,msg) {
    if (Math.random() > 0.1) return; // only log some errors

    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

不要な「window.error in undefined:0」エラーの処理はサイトのアーキテクチャによって異なりますが、すべてのAjax呼び出しを識別して、何かが失敗した場合に例外をスローすることができます(おそらく、stacktrace.jsを使用してスタックトレースを返します)。


67
私はこれが古い質問であることを知っていますが、いくつかのエラーをランダムに無視することを提案することは、今まで聞いた中で最悪のアイデアの1つです。
jbabey 2013

26
@jbabey:小規模なサイトの場合は適切ですが、10万人または数百万人のユーザーがいる大規模なサイトを実行している場合は、サーバー(またはインターネット)に冗長なログ要求をあふれさせる必要はありません。十分に大きいシステムでは、すべての実際のエラーが1日に数万回発生するため、この形式の制限は問題なく機能します。このアイデアは実際にはFacebookに実装されています。
Jens Roland

1
デバッグモードでのエラーのログ記録は、本番環境のエラーレポートを制限することと同じくらい重要である可能性が高いため、ログしきい値を制限する値を管理するためのソリューションが必要であることに気づくかもしれません。
フラッタロ2015年

2
@NickBull 2011年から2012年にかけて、多数のFacebook JavaScriptモジュールをリバースエンジニアリングしました。それは私がそれを見つけた場所です。
Jens Roland

1
@NickBullは私の古いファイルをチェックしましたが、まだありました。私はFacebookのブートローダーモジュールでこのトリックを見つけました:(if (global.logJSError) if (Math.random() < .01) logJSError('bootloader', {確かに、コードはすべてのエラーを抑制せず、タイムアウトエラーの特定のクラスのみを抑制します)
Jens Roland

7

IHMO、他のいくつかの言語(AFAIK:Python、Java)で行うように、JavaScriptでエラー処理を使用する必要があります。

読みやすさを向上させるには(そして、本当に大きな影響があるかどうかはわかりませんが、おそらくパフォーマンスを向上させるため)、次の場合にtry / catchブロックを使用する必要があります。

  • ラップするコードの部分は、アルゴリズム全体の重要な部分です。それが失敗した場合、それは可能性があります:

    • コードの次の部分でエラーを作成します(たとえば、varが見つからないため...)
    • ページが期待どおりに表示されないようにする(コンテンツまたはCSSに影響を与える)
    • 結果をユーザーに奇妙に見せます(コードの動作に影響します)
  • あなたが書いているコードはすべてのブラウザと互換性があるわけでないことを知っています

  • コードが失敗する可能性があることを計画した(if ... then ...ブロックで機能することを確認する他の方法がないため)
  • また、最終ユーザーを煩わせることなくデバッグしたい場合

最終的には、JavaScriptの専門家が他の要素を提供する可能性があります。

ボックスに私の2セント、

よろしく、

マックス


1
「ラップしたいコードの部分は、アルゴリズム全体の重要な部分です」-失敗の処理方法によって異なる場合があります。失敗時にアルゴリズムを続行する方法がないことがわかっている場合、try / catchを(たとえば)ネストされたループ内に埋め込むとパフォーマンスヒットが増えるため、全体をtry / catchでラップする方がよいでしょう。 。一方、例外に対して何らかのアクションを実行してアルゴリズムを続行できる場合は、よりきめの細かいtry / catchセットアップが必要になります。
nnnnnn 2011年

5

他の回答に加えて、1つの重要なことは、JavaScriptエラーオブジェクトと関数パラメーターで利用可能なコンテキストデータ使用することですwindow.onerror

スタックトレース(errorObject.stack)、ファイル名、行番号、列番号など。各ブラウザにはいくつかの違いがあることに注意してください...素敵なエラーを取得するために最善の努力をしてください。

コンソールオブジェクト自体にも問題がある可能性があります。私はこの1つに触発されたカスタムwindow.onerror関数と、このコードに触発された特定の標準エラーオブジェクトをトレースする特別な関数を使用します

もう1つの優れた点は、スタックトレースに近い場所にWebアプリケーションのバージョンを含めることです(コピーと貼り付けを迅速かつ安全に行うため)。また、開発者はブラウザコンソールを常に監視しているわけではなく、一部の問題が表示されない可能性があるため、開発モードではより積極的にエラー(アラート...)を表示する場合もあります。

また、使用することは避けてくださいを使用しthrow 'My message'、使用をthrow new Error('My message')読んで、あなたもカスタムエラーを持つことができ、この記事を

常にいくつかのコンテキストをエラー(バージョン、オブジェクトのID、カスタムメッセージなど)に追加し、外部エラー(外部データまたはシステムが失敗した状況)と内部エラーを区別してください。 / assertions(ご自身のシステムがめちゃくちゃになっています)、「契約による設計」について読んでください。

こちらがガイドです。

ライブラリやフレームワークのインターセプターのような一般的なエラー処理の使用も検討してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.