JavascriptとTypescriptでの高度なtry / catch / finally

try-catch-finally-blockの実装を詳しく見てみましょう

JavascriptとTypescriptでのエラー処理

ほとんどのプログラミング言語の場合と同様に、実行時にエラーが発生すると、JavascriptとTypescriptで「スロー」されます。スローされたエラーを処理しないと、アプリまたはサービスがクラッシュし、ユーザーエクスペリエンスが最悪になります。エラーが発生すると、保存されていない進行状況が失われ、ユーザーが長いプロセスを開始する可能性があります(たとえば、ユーザーが多くの情報を提供してプラットフォームに登録している場合)。その結果、信頼が失われたため、これらのユーザーが製品を二度と使用することはほとんどありません。

このような場合を処理するために、エラーを「キャッチ」することができます。 JavascriptとTypescriptのエラーをキャッチするには、コードを「try」ブロックでラップし、その後に「catch」ブロックを続けます。

async function getData(){
  try {
    // Call a dummy async 'fetch'-functoin
    const result = await fetch();
    return { result };
  } catch(error) {
    return { error };
  }
}

// ... later in your code ....

const { result, error } = await getData();

if (error){
  // ... handle error case.
}

// Access the results.

その結果、エラーはシステム全体に伝播せず、クラッシュにつながりますが、コードのスコープ内で直接処理されます。アプリやサービスがクラッシュすることはなく、エラーを処理するための軽減戦略を適用できます。

「最終的に」ブロックによる特別な取り扱い

エラーを処理するための追加の手順として、JavascriptとTypescriptは追加の「最終的に」キーワードを提供します。このような「finally」ブロックは、「try」ブロックと「catch」ブロックの両方が実行された後(エラーが発生した場合)、スコープ内のすべてのコードを実行します。

// This function is absolutely save
// to call. It fetches some data and 
// optionally catches a potential error.
//
// After everything's done, a 'finally'
// sends the error to our backend for logs,
// if there was any.
async function getData(){
  // In this case, we store the result
  // and error in mutable variables,
  // then return both.
  let result: Result;
  let error: Error;
  
  try {
    // Call a dummy async 'fetch'-function
    result = await fetch();
  } catch(e) {
    error = e;
  } finally {
    // After the whole try/catch has been
    // processed, we can log the error.
    if(error){
      await trackErrorInCloud(error);
    }
  }
  
  return { result, error };
}

// ... same as before ...

しかし、待ってください、もっとあります! 「try」または「catch」ブロックで結果を返しても、「finally」ブロックが実行されることをご存知ですか?これが私が意味することの例です。

// Same as the example before, but
// now we directly return from within
// each code block. And this is where
// a side effect can happen.
async function getData(){
  try {
    const result = await fetch();
    return { result };
  } catch(error) {
    return { error }
  } finally {
    //
    // WATCH OUT!
    //
    // Just for demo purpose, but this
    // line of code will override both
    // the return in 'try' as well as 'catch'!
    //
    // Returning inside of 'finally' is therefore
    // dangerous and will lead to hard-to-debug 
    // issues.
    return { finally: true };
  }
}

// data === { finally: true }
const data = await getData();
// Here's a better use case for
// finally.
async function getData(){
  let error: Error;
  
  try {
    const result = await fetch();
    return { result };
  } catch(e) {
    error = e;
    return { error }
  } finally {
    // No return in finally,
    // so it's safe to use.
    if(error){
      await logInCloud()
    }
  }
}

// if no error === { result: ... }
// if error === { error: ... }
const data = await getData();

概要

これまで見てきたように、JavascriptとTypescriptでのエラーの処理は非常に簡単で、アプリケーションの完全なクラッシュを回避できます。 「try」ブロックと「catch」ブロックで結果を返すという特別な処理は、「finally」ブロックを使用するときに知っておくと便利ですが、アンチパターンスタイルでコードを実装することを避けるために悪用しないでください。

提案

関連する

言語