JavaScript中級

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

導入

非同期処理は、JavaScriptにおける重要な要素であり、特にユーザー体験を向上させるために欠かせません。しかし、実際の開発現場では、非同期処理に関するアンチパターンが数多く存在し、それが原因でコードの可読性や保守性が低下することがあります。本記事では、具体的なシチュエーションを通じて、よくある失敗例とその改善策を探ります。

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

重要な概念の整理

非同期処理は、主にコールバック、Promise、async/awaitの3つの方法で実装されます。これらの手法は、非同期タスクを扱う際の流れを管理し、よりスムーズなユーザー体験を提供します。しかし、これらを正しく使わないと、コードが複雑になり、意図しない動作を引き起こすことがあります。

コード例(JavaScript)


// 非同期処理の例
function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const data = { id: 1, name: 'Sample Data' };
            resolve(data);
        }, 1000);
    });
}

async function displayData() {
    const data = await fetchData();
    console.log(data);
}

displayData();

コードの行ごとの解説

  1. fetchData関数はPromiseを返し、1秒後にデータを解決します。
  2. displayData関数はasync関数で、awaitを使用してfetchDataの結果を待ちます。
  3. 最終的に、データがコンソールに表示されます。

アンチパターン編

非同期処理における一般的なアンチパターンの一つは、「コールバック地獄」です。これは、コールバック関数をネストしてしまい、コードが深くなり、可読性が著しく低下する現象を指します。例えば、次のようなコードが考えられます。


function fetchData(callback) {
    setTimeout(() => {
        const data = { id: 1, name: 'Sample Data' };
        callback(data);
    }, 1000);
}

function processData(data, callback) {
    setTimeout(() => {
        const processedData = { ...data, processed: true };
        callback(processedData);
    }, 1000);
}

fetchData((data) => {
    processData(data, (processedData) => {
        console.log(processedData);
    });
});

このコードでは、fetchDataとprocessDataのコールバックがネストされ、可読性が損なわれています。この問題を解決するためには、Promiseやasync/awaitを使用することが効果的です。以下は、改善されたコードの例です。


function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => {
            const data = { id: 1, name: 'Sample Data' };
            resolve(data);
        }, 1000);
    });
}

function processData(data) {
    return new Promise((resolve) => {
        setTimeout(() => {
            const processedData = { ...data, processed: true };
            resolve(processedData);
        }, 1000);
    });
}

async function displayData() {
    const data = await fetchData();
    const processedData = await processData(data);
    console.log(processedData);
}

displayData();

この改善されたコードでは、Promiseを使用することでネストを解消し、可読性を向上させています。また、エラーハンドリングも簡単に実装できるため、より堅牢なコードが実現できます。

まとめ

  • コールバック地獄は非同期処理における一般的なアンチパターンです。
  • Promiseやasync/awaitを使用することで、コードの可読性と保守性を向上させることが可能です。
  • 非同期処理を適切に管理することで、より良いユーザー体験を提供できます。