javascriptの例外処理を✅

期限を設定した過去の自分を恨みながら粛々と機能追加を行なっている23期中野昴こと締め切り間に合わなそうで言い訳ばっか考えているです。

今回は例外処理について学習していきます。

例外処理とは

例外処理とは、プログラムの実行の継続を妨げる異常な事象(「例外」と呼ばれる)が発生した際に、その内容に応じて実行される処理のこと。

下記のような挙動を実現することも可能。

「存在しないページにアクセスした時に404エラーページを表示する。」

ポートフォリオで404ページを作成していると「お〜」ってなるそう。

では代表的な例外処理の構文を見ていきたい。

try...catch構文

try,catchで構成され、try内の処理を管理する時に使う構文。phpjavascriptでよく見られる。

試して、エラーをキャッチする。そのまんまである。

try,catchともう一つfinallyがある。

finally内の処理は例外の発生に関係なく必ず実行される。しかし、try,finallyの組み合わせのみだと例外処理をすることができない。

try {
    console.log("try節:この行は実行されます");
    // 未定義の関数を呼び出してReferenceError例外が発生する
    undefinedFunction();・・・1
    
} catch (error) {
    ・・・2
    console.log("catch節:この行は実行されます");
    console.log(error instanceof ReferenceError); // => true
    console.log(error.message); // => "undefinedFunction is not defined"
} finally {
    ・・・3
    console.log("finally節:この行は実行されます");
}

1 例外が発生したため、この行以下の文は実行されない。

2 例外が発生したあとはこのブロックが実行される。

3 このブロックは例外の発生に関係なく必ず実行される。

throw文

throw文では、開発者が意図的にエラーを投げることができる。

意図的に例外を起こすとは、ある条件と一致する場合に例外を発生させ、エラーメッセージを返すということを指している。

下記の例は、もしソフトドリンクが混じっていた場合にエラー文を表示する関数を書いている。

function checkSake(bottle){
  try{
    if (bottle === "ソフトドリンク"){
      throw '酒じゃありませんね〜';
    }

    console.log(bottle + '一本');
    console.log('酒です');
  } catch(e) {
    console.error(e);
  }
}

console.log('Start');

console.log(checkSake("ハイボール"));
console.log(checkSake("ソフトドリンク"));
console.log(checkSake("ビール"));

console.log('End');

> "Start"
> "ハイボール一本"
> "酒です"
> undefined
> 酒じゃありませんね〜
> undefined
> "ビール一本"
> "酒です"
> undefined
> "End"

エラーオブジェクト

ErrorオブジェクトのインスタンスErrornewして作成する。

引数にエラーが生じた時の文を書いておくことで、独自の例外処理を作成することができる。

// 渡された数値が0以上ではない場合に例外を投げる関数
function assertPositiveNumber(num) {
    if (num < 0) {
        throw new Error(`${num} is not positive.`);
    }
}

try {
    // 0未満の値を渡しているので、関数が例外を投げる
    assertPositiveNumber(-1);
} catch (error) {
    console.log(error instanceof Error); // => true
    console.log(error.message); // => "-1 is not positive."
}

例外処理

ビルトインエラー

例外処理には種類があり、状況に応じて出力されるエラー文が違う。このもともと組み込まれている種類をビルトインエラーという。

いくつか列挙してみる

ReferenceError

存在しない変数や関数などの識別子が参照された場合のエラー。

次のコードでは、存在しない変数を参照しているためReferenceError例外が投げられている。

try {
    // 存在しない変数を参照する
    console.log(x);
} catch (error) {
    console.log(error instanceof ReferenceError); // => true
    console.log(error.name); // => "ReferenceError"
    console.log(error.message); // エラーメッセージが表示される
}

SyntaxError

構文的に不正なコードを解釈しようとした場合のエラー。

基本的にSyntaxError例外は、JavaScriptを実行する前のパース段階で発生している。

そのため、実行前に発生する例外であるSyntaxErrortry...catch文ではcatchできない。

次のコードでは、eval関数を使って実行時にSyntaxErrorを発生させています。 eval関数は渡した文字列をJavaScriptとして実行する関数を指している。 実行時に発生したSyntaxErrorは、try...catch文でもcatchすることができる。。

try {
    // eval関数は渡した文字列をJavaScriptとして実行する関数
    // 正しくない構文をパースさせ、SyntaxErrorを実行時に発生させる
    eval("foo! bar!");
} catch (error) {
    console.log(error instanceof SyntaxError); // => true
    console.log(error.name); // => "SyntaxError"
    console.log(error.message); // エラーメッセージが表示される
}

TypeError

値が期待される型ではない場合のエラー。

いわゆるタイポのこと。

次のコードでは、関数ではないオブジェクトを関数呼び出ししているため、TypeError例外が投げられます。

try {
    // 関数ではないオブジェクトを関数として呼び出す
    const fn = {};
    fn();
} catch (error) {
    console.log(error instanceof TypeError); // => true
    console.log(error.name); // => "TypeError"
    console.log(error.message); // エラーメッセージが表示される
}

他に例外処理といえば、railsにはSentryというgemがある。どうやらrailsには限らないみたいだが。

sentryとは

you can trace performance issues to poor-performing api calls and slow database queries.

パフォーマンスの低いapiやクエリの遅いDBを探知することができる優れもの。

様々なフレームワーク、言語に対応している。

例えばrailsに組み込みたい場合は以下の通り

  1. Gemfileにsentry-railsを追加
gem "sentry-ruby"
gem "sentry-rails"
  1. config/initializers/sentry.rbに書き込む

config/initializers/sentry.rb

Sentry.init do |config|
  config.dsn = '<https://examplePublicKey@o0.ingest.sentry.io/0>'
  config.breadcrumbs_logger = [:active_support_logger, :http_logger]

  # To activate performance monitoring, set one of these options.
  # We recommend adjusting the value in production:
  config.traces_sample_rate = 0.5
  # or
  config.traces_sampler = lambda do |context|
    true
  end
end

たったこれだけでエラー時の挙動を追跡することができる。

[![Image from Gyazo](<https://i.gyazo.com/39a690e6f6ed81311cd027810363c4a7.png>)](<https://gyazo.com/39a690e6f6ed81311cd027810363c4a7>)

まとめ

  • try...catch構文はtryブロック内で発生した例外を処理できる
  • catch節とfinally節は、両方またはどちらか片方を記述する
  • throw文は例外を投げることができ、Errorオブジェクトを例外として投げる
  • Errorオブジェクトには、ECMAScript仕様や実行環境で定義されたビルトインエラーがある

Application Monitoring and Error Tracking Software

一言

眠い!!!!!