TypeScript上級

上級 TypeScriptで学ぶ非同期処理|アンチパターン編

導入

非同期処理は、現代のアプリケーション開発において不可欠な要素です。しかし、非同期処理に関する誤った実装は、予期せぬバグやパフォーマンスの低下を引き起こすことがあります。本記事では、TypeScriptを用いて非同期処理を扱う際のアンチパターンを掘り下げ、具体的な失敗例とその改善策を示します。

教科書レベルの解説(非同期処理)

重要な概念の整理

非同期処理は、主にコールバック、Promise、async/awaitの3つの方法で実現されます。コールバックはシンプルですが、ネストが深くなると可読性が低下します。Promiseは、非同期処理の結果を扱うための強力な手段ですが、エラーハンドリングが難しい場合があります。async/awaitは、Promiseの上に構築されており、直感的なコード記述を可能にします。

コード例(TypeScript)


async function fetchData(url: string): Promise {
    const response = await fetch(url);
    if (!response.ok) {
        throw new Error('Network response was not ok');
    }
    return await response.text();
}

async function processData() {
    try {
        const data = await fetchData('https://example.com/data');
        console.log(data);
    } catch (error) {
        console.error('Error fetching data:', error);
    }
}

processData();

コードの行ごとの解説

  1. async function fetchData(url: string): Promise { – 非同期関数を定義し、URLを引数として受け取ります。
  2. const response = await fetch(url); – 指定されたURLからデータを取得します。ここで、fetchの結果を待つことができます。
  3. if (!response.ok) { throw new Error('Network response was not ok'); } – レスポンスが正常でない場合、エラーをスローします。
  4. return await response.text(); – レスポンスのテキストを返します。
  5. async function processData() { – データを処理する別の非同期関数を定義します。
  6. const data = await fetchData('https://example.com/data'); – データを取得し、待機します。
  7. console.log(data); – 取得したデータをコンソールに出力します。
  8. catch (error) { console.error('Error fetching data:', error); } – エラーハンドリングを行います。
  9. processData(); – 非同期処理を開始します。

アンチパターン編

非同期処理における一般的なアンチパターンの一つは、コールバック地獄です。以下の例を見てみましょう。


function fetchDataWithCallback(url: string, callback: (data: string) => void) {
    fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            return response.text();
        })
        .then(data => {
            callback(data);
        })
        .catch(error => {
            console.error('Error fetching data:', error);
        });
}

fetchDataWithCallback('https://example.com/data', (data) => {
    console.log(data);
});

このコードは、fetchの結果をコールバックで処理していますが、ネストが深くなり可読性が低下します。また、エラーハンドリングが分散しているため、問題を追跡するのが難しくなります。

改善策としては、async/awaitを用いてコードをフラットに保つことが挙げられます。これにより、エラーハンドリングも一元化され、可読性が向上します。

まとめ

  • 非同期処理は、コールバック、Promise、async/awaitのいずれかで実装可能。
  • コールバック地獄を避けるため、async/awaitを活用して可読性を向上させる。
  • エラーハンドリングは一元化し、問題の追跡を容易にする。