web-dev-qa-db-ja.com

JavaScriptでtry-catch ...それは良い習慣ではありませんか?

javascripttry-catchブロックの規定があります。 Javaまたはその他の言語では、エラー処理が必須ですが、JavaScriptでそれらをより広範囲に使用している人はいないでしょう。それは良い習慣ではありませんかJavaScriptで必要ですか?

69
akp

アプリケーションでエラー条件を渡す方法として、throwエラーを回避する必要があります。

throwステートメントは、「これが発生することは決してないので、クラッシュして書き込みます。エレガントな方法で回復しないでください。」

try catchは、Hostオブジェクトまたは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は非常に高価であり、醜く、非同期操作では機能しないなどの問題もあります。

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

66
Raynos

JavaScriptの非同期の性質により、JavaScriptでのtry/catchは他の言語ほど強力ではありません。このスニペットを考えてみましょう:

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

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

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

_setTimeout(function () {
    do_something_that_calls_err(function(err) {
        alert("Something went wrong, namely this: " + err);
    }),
    1000);
_
32
tdammers

これらの回答の多くは少し古く、ES7の新機能asyncおよびawaitを考慮していません。

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

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

async/await here の詳細をご覧ください。 babel を使用してasync/awaitを使用できます。

25
Dana Woodman

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

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

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

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

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

16
user250878

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

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が普及し始めています。 try..catchの非同期形式であることを約束しますが、当然のことですが、

doSomething().then(
  doSomethingWithResult,
  doSomethingWithError
)

代わりに次のように書きます:

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

おそらく、JavaScriptでtry/catchがあまり使用されていないもう1つの理由は、Javascriptの非常に最初のバージョンでは構成が利用できなかったためです...後で追加されました。

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

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


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

3
Chuck Kollars

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

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

奇妙に聞こえるかもしれませんが、顧客が作成したページを使用していて、顧客がtech-savvy-coderでない限り、ページが例外をスローする場合、Javascriptエラーがクライアント側で発生します=方法はありません彼はあなたに問題が何であるかを伝えることができるでしょう。

"ページXは機能しません!"、と言って電話をかけるだけで、問題の原因とコード内の場所を見つけるのはあなた次第です。

代わりに警告ボックスを使用することで、彼が電話して次のようなことを言う可能性が高くなります:"ページXのボタンAをクリックすると、次のようなボックスが表示されます..."、私を信じて、バグを見つけやすくなります。

0
Marco Demaio