サーチ…
構文
- try {...} catch(エラー){...}
- try {...} finally {...}
- try {...} catch(エラー){...} finally {...}
- 新しいエラーを投げる([メッセージ]);
- スローエラー([メッセージ]);
備考
try
使用すると、実行中のエラーをテストするコードブロックを定義できます。
catch
使用すると、 try
ブロックにエラーが発生した場合に、実行するコードのブロックを定義できます。
finally
結果に関係なくコードを実行できます。ただし、tryブロックとcatchブロックの制御フロー文は、finallyブロックの実行が終了するまで中断されます。
約束との相互作用
例外とは、 約束ベースの非同期コードに対する拒否を同期コードにすることです。 promiseハンドラで例外がスローされた場合、そのエラーは自動的に捕捉され、代わりに約束を拒否するために使用されます。
Promise.resolve(5)
.then(result => {
throw new Error("I don't like five");
})
.then(result => {
console.info("Promise resolved: " + result);
})
.catch(error => {
console.error("Promise rejected: " + error);
});
Promise rejected: Error: I don't like five
非同期関数の提案 (ECMAScript 2017の一部であると予想される)は、これを逆方向に拡張します。拒否された約束を待っている場合、そのエラーは例外として発生します。
async function main() {
try {
await Promise.reject(new Error("Invalid something"));
} catch (error) {
console.log("Caught error: " + error);
}
}
main();
Caught error: Invalid something
エラーオブジェクト
JavaScriptのランタイムエラーはError
オブジェクトのインスタンスです。 Error
オブジェクトは、そのまま、またはユーザー定義の例外のベースとしても使用できます。文字列などの任意の型の値をスローすることは可能ですが、スタックトレースなどのデバッグ情報が正しく保存されるように、 Error
またはその派生形の1つを使用することを強く推奨します。
Error
コンストラクタの最初のパラメータは、人間が判読可能なエラーメッセージです。追加情報が他の場所にある場合でも、間違ったことの有用なエラーメッセージを常に指定するようにしてください。
try {
throw new Error('Useful message');
} catch (error) {
console.log('Something went wrong! ' + error.message);
}
オペレーションの順序と高度な考え
try catchブロックがなければ、未定義関数はエラーをスローして実行を停止します。
undefinedFunction("This will not get executed");
console.log("I will never run because of the uncaught error!");
エラーをスローし、2行目を実行しません:
// Uncaught ReferenceError: undefinedFunction is not defined
コードを実行し続けるようにそのエラーを確実に捕捉するには、他の言語に似たtry catchブロックが必要です。
try {
undefinedFunction("This will not get executed");
} catch(error) {
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I will run because we caught the error!");
さて、我々はエラーをキャッチし、私たちのコードが実行されることを確認することができます
// An error occured! ReferenceError: undefinedFunction is not defined(…)
// The code-block has finished
// I will run because we caught the error!
catchブロックでエラーが発生した場合はどうなりますか?
try {
undefinedFunction("This will not get executed");
} catch(error) {
otherUndefinedFunction("Uh oh... ");
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I won't run because of the uncaught error in the catch block!");
残りのcatchブロックは処理しません。finallyブロックを除いて実行が停止します。
// The code-block has finished
// Uncaught ReferenceError: otherUndefinedFunction is not defined(…)
あなたはいつもあなたのtry catchブロックを入れ子にすることができます。しかし、それは非常に乱雑になるので、あなたはすべきではありません..
try {
undefinedFunction("This will not get executed");
} catch(error) {
try {
otherUndefinedFunction("Uh oh... ");
} catch(error2) {
console.log("Too much nesting is bad for my heart and soul...");
}
console.log("An error occured!", error);
} finally {
console.log("The code-block has finished");
}
console.log("I will run because we caught the error!");
前の例のすべてのエラーをキャッチし、次のログを記録します。
//Too much nesting is bad for my heart and soul...
//An error occured! ReferenceError: undefinedFunction is not defined(…)
//The code-block has finished
//I will run because we caught the error!
では、どのようにしてすべてのエラーをキャッチできますか?定義されていない変数や関数については、そうすることはできません。
また、try / catchブロック内のすべての変数と関数をラップするべきではありません。これらの単純な例は、修正するまで一度だけ発生するためです。しかし、あなたが知っているオブジェクト、関数、およびその他の変数は存在しますが、そのプロパティやサブプロセスや副作用が存在するかどうかわからない場合や、状況によってはいくつかのエラー状態が予想される場合は、何らかの仕方で。ここには非常に基本的な例と実装があります。
信頼できないメソッドや例外をスローするメソッドを呼び出すための保護された方法がない場合:
function foo(a, b, c) {
console.log(a, b, c);
throw new Error("custom error!");
}
try {
foo(1, 2, 3);
} catch(e) {
try {
foo(4, 5, 6);
} catch(e2) {
console.log("We had to nest because there's currently no other way...");
}
console.log(e);
}
// 1 2 3
// 4 5 6
// We had to nest because there's currently no other way...
// Error: custom error!(…)
また、
function foo(a, b, c) {
console.log(a, b, c);
throw new Error("custom error!");
}
function protectedFunction(fn, ...args) {
try {
fn.apply(this, args);
} catch (e) {
console.log("caught error: " + e.name + " -> " + e.message);
}
}
protectedFunction(foo, 1, 2, 3);
protectedFunction(foo, 4, 5, 6);
// 1 2 3
// caught error: Error -> custom error!
// 4 5 6
// caught error: Error -> custom error!
私たちはエラーを捕まえ、やや異なった構文でも、すべての期待されるコードを処理します。いずれの方法でも動作しますが、より高度なアプリケーションを構築する際には、エラー処理を抽象化する方法について考え始める必要があります。
エラーの種類
JavaScriptには、6つの特定のコアエラーコンストラクタがあります。
EvalError
- グローバル関数eval()
に関して発生するエラーを表すインスタンスを生成します。InternalError
- JavaScriptエンジンの内部エラーがスローされたときに発生するエラーを表すインスタンスを作成します。例えば「過度の再帰」。 ( Mozilla Firefoxのみでサポートされています)RangeError
- 数値変数またはパラメータが有効範囲外にあるときに発生するエラーを表すインスタンスを作成します。ReferenceError
- 無効な参照を逆参照するときに発生するエラーを表すインスタンスを作成します。SyntaxError
-eval()
コードを解析中に発生する構文エラーを表すインスタンスを作成します。TypeError
- 変数またはパラメータが有効な型でない場合に発生するエラーを表すインスタンスを作成します。URIError
-encodeURI()
またはdecodeURI()
に無効なパラメータが渡されたときに発生するエラーを表すインスタンスを作成します。
エラー処理の仕組みを実装している場合は、どの種類のエラーをコードからキャッチしているかを確認できます。
try {
throw new TypeError();
}
catch (e){
if(e instanceof Error){
console.log('instance of general Error constructor');
}
if(e instanceof TypeError) {
console.log('type error');
}
}
そのような場合、 e
はTypeError
インスタンスになります。すべてのエラータイプは、ベースコンストラクターError
拡張します。したがって、 Error
インスタンスでもあります。
そのことを念頭に置いておくと、 e
をError
インスタンスにすることはほとんどの場合役に立たないことがわかります。