javascriptのtry-catch ...は良い習慣ではありませんか?


69

javascriptにtry-catchブロックの規定があります。Javaやその他の言語ではエラー処理が必須ですが、JavaScriptでエラーを使用している人は誰もいません。それは良い習慣ではありませんか、それとも私たちはJavaScriptでそれらを必要としませんか?


2
While in java or *any other language* it is mandatory to have error handling...- あんまり。Java、はい。ただし、try-catchを要求しない言語はたくさんあります(C#など)。
ジムG.

非同期環境では使用できないためです。私は...など、何かに何かを変換することにより、例えば、下の抽象レベルで同期コードによって、多くの場合、それらを使用する
inf3rno

サーバー側のコードには、クライアント側のコードよりも多くのtry-catchが表示されるはずです。あなたが知っているクライアント側のコードのほとんどは、重要なことは何もしていません。ほとんどのアプリケーションやブラウザ側の状況では、あらゆるエラーから回復するよりも、パイプでKBを最小化する方が重要です。
svidgen

多分およびいずれか(モナド)を使用してキャッチしようとすることを避けるための別の方法が1つあります。ノードでWebスクレイパーを作成しました。それを使用してtry catchをすべて削除することができました。
user93

回答:


66

一つは避けるべきであるthrowアプリケーションで周りのエラー条件を渡す方法として、エラーを。

このthrowステートメントは、「これは絶対に起こらないでください。クラッシュして燃えないようにしてください。エレガントに回復しないでください」

try catch ただし、ホストオブジェクトまたはECMAScriptがエラーをスローする可能性がある状況で使用されます。

例:

var json
try {
    json = JSON.parse(input)
} catch (e) {
    // invalid json input, set to null
    json = null
}

node.jsコミュニティの推奨事項は、最初の引数として、コールバックでエラーを渡すことです(非同期操作でのみエラーが発生するため)

fs.readFile(uri, function (err, fileData) {
    if (err) {
        // handle
        // A. give the error to someone else
        return callback(err)
        // B. recover logic
        return recoverElegantly(err)
        // C. Crash and burn
        throw err
    }
    // success case, handle nicely
})

try / catchのような他の問題もありますが、これは非常に高価であり、見苦しく、非同期操作では機能しません。

したがって、同期操作はエラーをスローしてはならず、非同期操作では機能しないため、ホストオブジェクトまたはECMAScriptによってスローされたエラーを除き、だれもtry catchを使用しません。


2
誰も try catchを使用しないとは言いませんが、ほとんどの場合、それは仕事にとっては間違ったツールです。本当に例外的な状況がある場合、をスローする価値がありますErrorが、それらはほとんどありません。
zzzzBov

7
@zzzzBovケースC、クラッシュ、および書き込みのエラーをスローしても何も問題はありません。エラーをキャッチして回復する必要があるとは思わない。たとえばdocument.getElementById、要素が存在しない場合はスローせず、単にを返しますnull。ほとんどすべての場合に同じことができます
Raynos

4
@Raynos、同期関数からのスローは完全に受け入れられ、そのユースケースで理にかなっています。エラーをスローすることは同期するため、コールバックにエラーを返すことは非同期になります。
sbartell

@Raynosには、クライアント側(非ノード環境)のフロー制御にエラー/例外を使用しないようにするための良いアドバイスがありますか?StackOverflowでこの投稿を見つけましたが、ほとんどJava向けです
13

@ b.long simple。これまでエラーをスローしないでください。問題が解決しました。
レイノス

32

Javascriptのtry / catchは、Javascriptの非同期の性質により、他の言語ほど安全ではありません。このスニペットを検討してください。

try {
    setTimeout(function() {
        do_something_that_throws();
    }, 1000);
}
catch (e) {
    alert("You won't see this!");
}

問題は、制御フローが実行されるtrydo_something_that_throws()にブロックを離れるため、コールバック内でスローされたエラーがキャッチされないことです。

したがって、多くの場合、try / catchは基本的に不適切であり、何かが非同期にコードを実行するかどうかは必ずしも明らかではありません。幸いなことに、独特のシングルスレッド非同期コールバックのイディオムと実際のクロージャーのサポートを備えたjavascriptは、エレガントな代替手段を提供します。継続渡しスタイルのエラー処理です。エラーとして適切な応答を関数として渡すだけです。例えば:

setTimeout(function () {
    do_something_that_calls_err(function(err) {
        alert("Something went wrong, namely this: " + err);
    }),
    1000);

5
他の言語でも防弾ではありません。そのコードを非同期コールバックをサポートする言語に移植すると、それも失敗します。
Raynos

2
@レイノス:あなたは正しい。ただし、他の言語(または、それらをサポートする文化)は、Javascriptのようにこれを非同期コールバックのイディオムにあまり取り入れません。また、他のほとんどの環境のマルチスレッドの性質により、try / catchの欠点はより明白であり、他の多くの警告に囲まれているため、人々はマルチスレッド/非同期コールバックの状況で自然に慎重に踏み、潜在的な落とし穴をよりよく認識しています。
-tdammers

これは本当にJavaScriptの「非同期の性質」によるものですか?私が見る限り、Try / Catchは理論的には識別子が字句的に閉じられる方法と同じように字句的に動作するようにできます。JavaScriptでそのように機能することはありません。
ブライアンゴードン

2
Node.jsのでは> = 0.8、非同期でキャッチ/しようとすることが可能となる注目に値する、私の質問を参照してください。stackoverflow.com/questions/14301839/...
ベンジャミンGruenbaum

同期try-catchに代わる唯一の方法は、非同期継続渡しスタイルですか?
CMCDragonkai

23

これらの回答の多くは少し古いものであり、新しいES7機能asyncとを考慮していませんawait

async/ awaitを使用すると、必要に応じて非同期制御フローを取得できます。

async function email(address) {
  try {
    // Do something asynchronous that may throw...
    await sendEmail({ to: address, from: 'noreply@domain.com`, subject: 'Hello' })
  } catch(err) {
    if (err instanceof SomeCustomError) {
      elegantlyHandleError(err)
    } else {
      throw err
    } 
  }
})

async/ awaitこちらの詳細をご覧ください。あなたは使用することができますasync/ await今使ってバベルを


しかし、それは同期コードに似ている
アトゥールアグラワル

@AtulAgrawalはい、それがポイントです。Async / awaitを使用すると、非同期コードを同期スタイルで記述できるため、「コールバック地獄」や多くのプロミスの連鎖を回避できます。私の意見では非同期コードを書くのはとても楽しい方法です
ダナウッドマン

非同期コードから同期コードを作成する場合、javascriptを使用する利点は何ですか。ほとんどの人が非同期の性質のためにJavaScriptを使用しているため
Atul Agrawal

2
@AtulAgrawalを使用すると、両方の長所を活用できます(上記のコードは引き続き非同期で実行されるため、スレッドのすべてを解放するため)非同期の言語の性質を享受し、よりプログラマーに優しいコーディングスタイルの利点を活用できます。ただし、問題がないわけではありません
...-ZenMaster

15

javascriptのtry-catchは、それらを実装する他の言語と同様に有効で便利です。javascriptで他の言語ほど使用されていない主な理由が1つあります。javascriptが見苦しいスクリプト言語と見なされるのと同じ理由で、javascriptプログラマが本物のプログラマではないと考える理由と同じ理由です。

  • Javascriptは信じられないほどアクセスしやすく、普及している言語です

非常に多くの人が(ブラウザでサポートされている唯一の言語のために)javascriptにさらされているという単なる事実は、多くの専門外のコードがそこにあることを意味します。もちろん、多くの小さな理由もあります。

  • javascriptのいくつかのものは非同期であり、したがってcatchできない(非同期のもの)
  • try-catchがパフォーマンスに大きな打撃を与える方法については、あまりにも誇張された話があります。それは持っているパフォーマンスヒットのビットを、ほとんどのコードのために、それはそれだけの価値があります。
  • javascriptは(残念ながら)静かにエラーを無視する方法で実装されました(たとえば、文字列を自動的に数字に変更する)

とにかく、try-catch 使用する必要がありますが、もちろん、他のすべてのプログラミングと同様に、それらを適切に使用する方法を学ぶ必要があります。


3
そして、なぜあなたはダウンボートをしたのでしょうか?
user250878

同意した。受け入れられた答えは一般的に正しいと思いますが、ネイティブオブジェクトを処理するとき以外に、try-catchを使用し、さらにはthrowを使用する正当な理由があります。エラーがコールバックに渡されるのではなくスローされると、それ以上の実行を停止し、スタックを処理可能な最初のブロックにジャンプします。これは大きな利点であり、特に深いネストが含まれる同期操作には最適です。例外が「悪い」(明らかな理由以外の理由で)ことを示唆するのはおかしいようです-実際、それらはユニークな「力」を持つ非常に便利なツールです。
セミコロン14年

2
jQueryのソースコードを読むのに時間をかけたことがありますか?受け入れられた答えで言及されているまさにそのシナリオを除いて、そこにトライキャッチはほとんどありません:エラーをスローするネイティブ/ホストオブジェクトを検出して使用します。try-catchをあまり使用しないコード(jQueryのような)を呼び出すことは、「プロではない」というのはばかげているようです。正直に言うと、try-catchのような言語機能を使いすぎる傾向があるのは、特にJavaから来た新しいJavascriptプログラマーだと思います。
スティンデウィット

6

try..catchJavaScriptでまれな理由の多くは、言語のエラーに対する耐性が非常に高いためだと思います。ほとんどの状況は、コードチェック、適切なデフォルト設定、および非同期イベントを使用して処理できます。場合によっては、単にパターンを使用するだけで問題を防ぐことができます。

function Foo() {
    //this may or may not be called as a constructor!!
    //could accidentally overwrite properties on window
}

function Bar() {
    if (!(this instanceof Bar)) {
        return new Bar();
    }
    //this will only work on Bar objects, and wont impact window
}

例外を発生させる他の言語の主要な問題のいくつかは、JSには存在しません。ほとんどの場合、型キャストは必要ありません。代わりに、一般的に推奨される方法は機能チェック(特定のインターフェースの強制)です。

function doFoo(arg) {
    if (arg.foo) {
        arg.foo();
    } else {
        Bar.prototype.foo.call(arg);
    }
}

言語にasync/ awaitを追加するtry..catchと、より一般的になります。Promiseはの非同期形式であるためtry..catch、予想されるはずです。

doSomething().then(
  doSomethingWithResult,
  doSomethingWithError
)

代わりに次のように記述します。

try {
  const result = await doSomething()
  doSomethingWithResult(result)
} catch (e) {
  doSomethingWithError(e)
}

3

Javascriptでtry / catchがあまり使用されない別の理由として、Javascriptの最初のバージョンではコンストラクトが使用できなかったことが考えられます...それは後で追加されました。

その結果、一部の古いブラウザではサポートされていません。(実際、古いブラウザではパーサー/構文エラーを引き起こす可能性があります。これは、他のほとんどのタイプのエラーよりも「防御的にプログラムする」ことが難しいものです。)

さらに重要なことに、最初は利用できなかったため、最初にリリースされたJavascript組み込み関数(多くの言語で「ライブラリ」関数と呼ばれるもの)はそれを使用しません。(「スロー」ではなく、問題が発生したときに「null」を返す場合、someobject.somefunction()からエラーを「キャッチ」することはあまりうまくいきません。)


さらに考えられるもう1つの理由は、try / catchメカニズムが最初は必要ないように思われたということです(それでも、それほど有用ではないようです)。呼び出しが定期的にいくつかのレベルの深さにネストされている場合にのみ必要です。何らかの種類のERRNOを返すだけで、直接呼び出しでは問題なく機能します(利用可能な場合はいつでも本当に役立つように、ほとんどの言語のベストプラクティスは、深くネストされた呼び出しではなく、どこでも使用することです)。Javascriptロジックは元々小さくシンプルであることが期待されていたため(結局、これは単なるWebページの付属物です)、関数呼び出しは深くネストされることは想定されていなかったため、try / catchメカニズムは必要ないように思われました。


3
いやいやいや、絶対にそうではない。古いエンジンは長い間問題ではなく、一般的にjavascriptコミュニティは正当化されると古いものを素早くドロップします。現在、JavaScript開発者の大部分はIE6以降です。
カミロマーティン14

0

Javascriptクライアント側コードで例外をスローすると、ページのデバッグが難しくなるため、あまり使用されていないと思います。

例外をスローするよりも、通常、すべてのアラートボックスを表示することを好みます(つまりalert("Error, invalid...");

それは奇妙に聞こえるかもしれませんが、顧客は、あなたが構築されたページを使用して、ページが例外をスローした場合Javascriptのエラーは、クライアント側で起こり、顧客がでない限り、ハイテクに精通し-コーダ彼が今まで知ることができます方法はありません問題は何ですか。

「おい、ページXが機能しない!」と言っただけで、彼はあなたに電話します。

代わりにアラートボックスを使用することで、「ページXのボタンAをクリックすると、「...」というボックスが表示されます」というようなメッセージを呼び出して言う可能性が高くなります。不具合。

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