JavaScriptのPromiseとAsync/Awaitの違いと効果的な使い分け

JavaScriptの非同期処理は、現代のWeb開発において不可欠な技術です。この非同期処理を扱うための基本的な手段として、PromiseとAsync/Awaitが用いられます。PromiseはES6で導入され、複雑な非同期処理をシンプルに管理するための方法です。一方、Async/AwaitはES8で導入され、Promiseをさらに簡単に扱うための構文です。本記事では、PromiseとAsync/Awaitの違いと、それぞれの使い分けについて詳しく解説します。これにより、JavaScriptの非同期処理を効果的に活用するための知識を身につけることができます。

目次

非同期処理とは何か

非同期処理とは、プログラムが特定の操作を待つことなく次の操作を実行することを指します。これは、特に時間のかかる操作(例えば、ネットワークリクエストやファイルの読み書き)を実行する際に重要です。同期処理では、これらの操作が完了するまで他の操作が停止してしまいますが、非同期処理では並行して他の操作を進めることができます。

非同期処理の重要性

非同期処理は、以下の理由から重要です。

  • パフォーマンス向上:ユーザーインターフェースが操作中も応答し続けるため、アプリケーション全体のパフォーマンスが向上します。
  • ユーザーエクスペリエンスの向上:ユーザーは長時間の待ち時間を感じることなく、アプリケーションを利用できます。
  • 効率的なリソース利用:CPUやメモリリソースを効率的に利用し、待ち時間を減らすことができます。

非同期処理を理解し適切に利用することで、よりスムーズで反応の良いアプリケーションを開発することができます。

Promiseの基本

Promiseは、JavaScriptにおける非同期処理を扱うためのオブジェクトです。Promiseは将来の完了または失敗を表し、その結果に対する処理を定義することができます。Promiseは、非同期操作の結果を扱うために、成功(resolve)と失敗(reject)の2つの状態を持ちます。

Promiseの構文

Promiseの基本的な構文は以下の通りです。

let promise = new Promise((resolve, reject) => {
    // 非同期処理
    if (/* 成功条件 */) {
        resolve('成功の結果');
    } else {
        reject('失敗の理由');
    }
});

Promiseの使い方

Promiseを利用するためには、thencatchメソッドを用います。thenメソッドはPromiseが成功した場合の処理を、catchメソッドは失敗した場合の処理を定義します。

promise
    .then(result => {
        console.log('成功:', result);
    })
    .catch(error => {
        console.log('失敗:', error);
    });

Promiseの例

以下は、fetch関数を使用してデータを取得する例です。

fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => {
        console.log('データを取得:', data);
    })
    .catch(error => {
        console.error('エラー:', error);
    });

このように、Promiseを使用することで、非同期処理を直線的に記述し、可読性を向上させることができます。Promiseは多くのライブラリやフレームワークで広く使用されており、JavaScriptの非同期処理の基本となる概念です。

Async/Awaitの基本

Async/Awaitは、Promiseをより簡潔に扱うための構文であり、JavaScriptの非同期処理を同期処理のように記述することができます。Async/Awaitは、非同期関数(async function)内でのみ使用でき、awaitキーワードはPromiseの解決を待つために使用されます。

Async/Awaitの構文

Async関数の基本的な構文は以下の通りです。

async function exampleFunction() {
    try {
        let result = await asyncOperation();
        console.log('成功:', result);
    } catch (error) {
        console.log('失敗:', error);
    }
}

Async/Awaitの使い方

Async/Awaitを利用することで、Promiseチェーンをシンプルにし、非同期処理のフローを直線的に記述することができます。

async function fetchData() {
    try {
        let response = await fetch('https://api.example.com/data');
        let data = await response.json();
        console.log('データを取得:', data);
    } catch (error) {
        console.error('エラー:', error);
    }
}

fetchData();

Async/Awaitの例

以下は、fetch関数を使用してデータを取得する例です。Promiseチェーンを使った場合と比べて、コードがシンプルで読みやすくなっています。

async function getData() {
    try {
        let response = await fetch('https://api.example.com/data');
        let data = await response.json();
        console.log('データを取得:', data);
    } catch (error) {
        console.error('エラー:', error);
    }
}

getData();

このように、Async/Awaitを使用することで、非同期処理を同期処理のように記述できるため、コードの可読性とメンテナンス性が向上します。Async/Awaitは、特に複雑な非同期処理を扱う際に非常に有用です。

Promiseの利点と欠点

Promiseを使用することで、非同期処理をより効果的に管理できますが、いくつかの利点と欠点があります。

Promiseの利点

1. コードの可読性向上

Promiseを使用することで、コールバック地獄(callback hell)を避けることができ、コードの可読性が大幅に向上します。

doSomething()
    .then(result => doSomethingElse(result))
    .then(newResult => doThirdThing(newResult))
    .then(finalResult => console.log('最終結果:', finalResult))
    .catch(error => console.error('エラー:', error));

2. エラーハンドリングの一元化

Promiseはチェーン内で発生するエラーをcatchメソッドで一元的に処理できます。これにより、エラーハンドリングが簡素化されます。

3. 非同期処理のシンプルな構成

Promiseを使うと、非同期処理の開始と完了の状態を簡単に管理できます。非同期操作が成功したか失敗したかを直感的に理解できます。

Promiseの欠点

1. 可読性の低下

Promiseチェーンが長くなると、コードの可読性が低下する可能性があります。特に、複雑な非同期操作を扱う場合は、構造が分かりにくくなることがあります。

doSomething()
    .then(result => {
        return doSomethingElse(result)
            .then(newResult => doThirdThing(newResult))
            .then(finalResult => {
                console.log('最終結果:', finalResult);
            });
    })
    .catch(error => console.error('エラー:', error));

2. ネストの増加

Promiseの使用は、場合によってはネストが深くなる可能性があります。ネストが深くなると、コールバック地獄ほどではないものの、コードの追跡が難しくなります。

3. エラーハンドリングの複雑さ

Promiseチェーン内で複数のcatchブロックを使用する場合、どのcatchがどのエラーを処理しているのかが不明確になることがあります。

Promiseは強力な非同期処理手段ですが、特定のシナリオではその欠点が影響することもあります。これらの利点と欠点を理解することで、Promiseを適切に活用し、最適な非同期処理を実現できます。

Async/Awaitの利点と欠点

Async/Awaitは、非同期処理をシンプルかつ直感的に記述するための構文です。Promiseと比較していくつかの利点と欠点があります。

Async/Awaitの利点

1. コードの可読性向上

Async/Awaitを使用すると、非同期コードが同期コードのように見えるため、可読性が大幅に向上します。

async function example() {
    try {
        const result = await doSomething();
        const newResult = await doSomethingElse(result);
        const finalResult = await doThirdThing(newResult);
        console.log('最終結果:', finalResult);
    } catch (error) {
        console.error('エラー:', error);
    }
}

2. ネストの削減

Async/Awaitを使用することで、Promiseチェーンに比べてネストが少なくなり、コードが簡潔になります。

3. エラーハンドリングの簡素化

try...catch構文を使用して、同期コードと同じ方法でエラーを処理できます。これにより、エラーハンドリングが直感的になります。

Async/Awaitの欠点

1. ブラウザ互換性の問題

Async/AwaitはES8で導入されたため、古いブラウザではサポートされていないことがあります。Polyfillやトランスパイラが必要になる場合があります。

2. 非同期操作の並列実行の難しさ

Async/Awaitは直列的な非同期操作には適していますが、並列実行には不向きです。Promise.allを併用する必要があります。

async function fetchData() {
    try {
        const [result1, result2] = await Promise.all([fetch(url1), fetch(url2)]);
        console.log('結果1:', result1);
        console.log('結果2:', result2);
    } catch (error) {
        console.error('エラー:', error);
    }
}

3. 設定が複雑な場合がある

Async/Awaitを使用する場合、関数全体をasyncで宣言しなければならず、コードベース全体の設計が少し複雑になることがあります。

Async/Awaitは、Promiseの欠点を補いながら、非同期処理をより直感的に扱うための強力な手段です。特に複雑な非同期処理が多く含まれる場合に、その利点が最大限に発揮されます。

PromiseとAsync/Awaitの使い分け

PromiseとAsync/Awaitは、どちらもJavaScriptの非同期処理を管理するための強力なツールですが、状況に応じて使い分けることで、その利点を最大限に活用できます。ここでは、具体的なシナリオに基づいて、どちらを使用するべきかを説明します。

簡単な非同期処理

単純な非同期操作や、少数の非同期ステップがある場合は、Promiseが適しています。Promiseは、そのシンプルさと直感的なチェーン構造により、短い非同期フローで特に効果的です。

fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => {
        console.log('データ:', data);
    })
    .catch(error => {
        console.error('エラー:', error);
    });

複雑な非同期処理

複数の非同期操作が連続する場合や、非同期処理のフローが複雑になる場合は、Async/Awaitが優れています。Async/Awaitは、非同期コードを同期コードのように直線的に記述できるため、可読性とメンテナンス性が向上します。

async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log('データ:', data);
    } catch (error) {
        console.error('エラー:', error);
    }
}

fetchData();

複数の非同期操作の並列実行

複数の非同期操作を並列で実行したい場合は、Promise.allとAsync/Awaitを組み合わせて使用することが適しています。これにより、複数の非同期処理を同時に実行し、そのすべてが完了するまで待つことができます。

async function fetchMultipleData() {
    try {
        const [data1, data2] = await Promise.all([
            fetch('https://api.example.com/data1').then(response => response.json()),
            fetch('https://api.example.com/data2').then(response => response.json())
        ]);
        console.log('データ1:', data1);
        console.log('データ2:', data2);
    } catch (error) {
        console.error('エラー:', error);
    }
}

fetchMultipleData();

エラーハンドリングの一元化

非同期処理中のエラーハンドリングを一元化したい場合は、Async/Awaitを使用する方がわかりやすくなります。try...catch構文を使うことで、同期処理のエラーハンドリングと同様に扱うことができます。

async function processData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        if (!data) {
            throw new Error('データが見つかりません');
        }
        console.log('データ:', data);
    } catch (error) {
        console.error('エラー:', error);
    }
}

processData();

これらの例からわかるように、PromiseとAsync/Awaitを使い分けることで、JavaScriptの非同期処理をより効果的に管理できます。シンプルな非同期処理にはPromise、複雑なフローや並列処理にはAsync/Awaitを選択するのが最適です。

実践例:Promiseの活用

Promiseを利用することで、非同期処理を管理しやすくなり、コードの可読性が向上します。ここでは、Promiseを使った具体的なコーディング例をいくつか紹介します。

データの取得と処理

以下の例では、APIからデータを取得し、そのデータを処理してコンソールに出力する方法を示します。

function fetchData() {
    return fetch('https://api.example.com/data')
        .then(response => {
            if (!response.ok) {
                throw new Error('ネットワーク応答が正しくありません');
            }
            return response.json();
        });
}

function processData(data) {
    return new Promise((resolve, reject) => {
        if (data) {
            resolve(`データが正常に処理されました: ${data}`);
        } else {
            reject('データが空です');
        }
    });
}

fetchData()
    .then(data => processData(data))
    .then(result => {
        console.log(result);
    })
    .catch(error => {
        console.error('エラー:', error);
    });

複数の非同期操作の連鎖

次の例では、複数の非同期操作を連鎖させて実行し、最終的な結果を処理します。

function firstAsyncOperation() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('最初の操作完了');
        }, 1000);
    });
}

function secondAsyncOperation(result) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(`${result} -> 次の操作完了`);
        }, 1000);
    });
}

function thirdAsyncOperation(result) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(`${result} -> 最後の操作完了`);
        }, 1000);
    });
}

firstAsyncOperation()
    .then(result => secondAsyncOperation(result))
    .then(result => thirdAsyncOperation(result))
    .then(finalResult => {
        console.log('すべての操作が完了しました:', finalResult);
    })
    .catch(error => {
        console.error('エラー:', error);
    });

ファイルの読み込みと処理

以下の例では、ファイルを非同期で読み込み、その内容を処理する方法を示します。この例では、Node.jsのfsモジュールを使用します。

const fs = require('fs').promises;

function readFile(filePath) {
    return fs.readFile(filePath, 'utf-8');
}

function processFileContent(content) {
    return new Promise((resolve, reject) => {
        if (content) {
            resolve(`ファイルの内容が処理されました: ${content}`);
        } else {
            reject('ファイルの内容が空です');
        }
    });
}

readFile('example.txt')
    .then(content => processFileContent(content))
    .then(result => {
        console.log(result);
    })
    .catch(error => {
        console.error('エラー:', error);
    });

これらの実践例から、Promiseを使用することで、非同期処理を効率的に管理し、コードの可読性と保守性を向上させることができることがわかります。Promiseは、シンプルな非同期処理から複雑な非同期処理まで、幅広いシナリオで活用できます。

実践例:Async/Awaitの活用

Async/Awaitは、非同期処理を同期処理のように記述できるため、コードの可読性と保守性が向上します。ここでは、Async/Awaitを使った具体的なコーディング例をいくつか紹介します。

データの取得と処理

以下の例では、APIからデータを取得し、そのデータを処理してコンソールに出力する方法を示します。

async function fetchData() {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
        throw new Error('ネットワーク応答が正しくありません');
    }
    return await response.json();
}

async function processData(data) {
    if (data) {
        return `データが正常に処理されました: ${data}`;
    } else {
        throw new Error('データが空です');
    }
}

async function executeAsyncOperations() {
    try {
        const data = await fetchData();
        const result = await processData(data);
        console.log(result);
    } catch (error) {
        console.error('エラー:', error);
    }
}

executeAsyncOperations();

複数の非同期操作の連鎖

次の例では、複数の非同期操作を連鎖させて実行し、最終的な結果を処理します。

function delayOperation(ms, result) {
    return new Promise(resolve => setTimeout(() => resolve(result), ms));
}

async function executeMultipleAsyncOperations() {
    try {
        const result1 = await delayOperation(1000, '最初の操作完了');
        const result2 = await delayOperation(1000, `${result1} -> 次の操作完了`);
        const result3 = await delayOperation(1000, `${result2} -> 最後の操作完了`);
        console.log('すべての操作が完了しました:', result3);
    } catch (error) {
        console.error('エラー:', error);
    }
}

executeMultipleAsyncOperations();

ファイルの読み込みと処理

以下の例では、ファイルを非同期で読み込み、その内容を処理する方法を示します。この例では、Node.jsのfsモジュールを使用します。

const fs = require('fs').promises;

async function readFile(filePath) {
    return await fs.readFile(filePath, 'utf-8');
}

async function processFileContent(content) {
    if (content) {
        return `ファイルの内容が処理されました: ${content}`;
    } else {
        throw new Error('ファイルの内容が空です');
    }
}

async function executeFileOperations() {
    try {
        const content = await readFile('example.txt');
        const result = await processFileContent(content);
        console.log(result);
    } catch (error) {
        console.error('エラー:', error);
    }
}

executeFileOperations();

APIからのデータ取得と一括処理

以下の例では、複数のAPIからデータを並列で取得し、そのデータを一括処理します。

async function fetchDataFromApis() {
    const urls = [
        'https://api.example.com/data1',
        'https://api.example.com/data2',
        'https://api.example.com/data3'
    ];

    try {
        const responses = await Promise.all(urls.map(url => fetch(url)));
        const dataPromises = responses.map(response => response.json());
        const data = await Promise.all(dataPromises);
        console.log('取得したデータ:', data);
    } catch (error) {
        console.error('エラー:', error);
    }
}

fetchDataFromApis();

これらの実践例から、Async/Awaitを使用することで、非同期処理をよりシンプルかつ直感的に記述できることがわかります。特に複雑な非同期操作を含む場合やエラーハンドリングが重要な場合に、Async/Awaitは非常に有効です。

エラーハンドリング

非同期処理においてエラーハンドリングは重要な要素です。PromiseとAsync/Awaitのエラーハンドリング方法を理解することで、より堅牢なコードを書くことができます。

Promiseのエラーハンドリング

Promiseのエラーハンドリングはcatchメソッドを使用して行います。thenチェーン内のどこかでエラーが発生すると、catchメソッドが呼び出されます。

fetch('https://api.example.com/data')
    .then(response => {
        if (!response.ok) {
            throw new Error('ネットワーク応答が正しくありません');
        }
        return response.json();
    })
    .then(data => {
        console.log('データ:', data);
    })
    .catch(error => {
        console.error('エラー:', error);
    });

この例では、fetchが成功したかどうかをチェックし、失敗した場合にはエラーをスローします。エラーはcatchメソッドでキャッチされ、エラーメッセージがコンソールに出力されます。

Async/Awaitのエラーハンドリング

Async/Awaitのエラーハンドリングは、try...catch構文を使用して行います。これは、同期コードのエラーハンドリングと同じ方法です。

async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) {
            throw new Error('ネットワーク応答が正しくありません');
        }
        const data = await response.json();
        console.log('データ:', data);
    } catch (error) {
        console.error('エラー:', error);
    }
}

fetchData();

この例では、fetchが成功したかどうかをチェックし、失敗した場合にはエラーをスローします。エラーはcatchブロックでキャッチされ、エラーメッセージがコンソールに出力されます。

エラーハンドリングのベストプラクティス

エラーハンドリングを効果的に行うためのベストプラクティスを以下に示します。

1. エラーメッセージの明確化

エラーメッセージは明確で具体的にしましょう。これにより、問題の原因を特定しやすくなります。

if (!response.ok) {
    throw new Error(`HTTPエラー! ステータス: ${response.status}`);
}

2. グローバルエラーハンドリング

アプリケーション全体でエラーをキャッチするためのグローバルエラーハンドリングを設定しましょう。これは、特にPromiseチェーンで有効です。

window.addEventListener('unhandledrejection', event => {
    console.error('未処理のPromise拒否:', event.promise, '理由:', event.reason);
});

3. ログと通知

エラーが発生した場合、エラーログを記録し、必要に応じて通知を送る仕組みを構築しましょう。

async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) {
            throw new Error(`HTTPエラー! ステータス: ${response.status}`);
        }
        const data = await response.json();
        console.log('データ:', data);
    } catch (error) {
        console.error('エラー:', error);
        // 例: エラーをサーバーに送信
        // await sendErrorLogToServer(error);
    }
}

これらのベストプラクティスを取り入れることで、エラーを適切に管理し、アプリケーションの信頼性と保守性を向上させることができます。PromiseとAsync/Awaitのエラーハンドリングを正しく理解し、実践することで、より堅牢な非同期コードを実装することができます。

パフォーマンス比較

PromiseとAsync/AwaitはどちらもJavaScriptの非同期処理を効率的に行うための手段ですが、それぞれのパフォーマンスには違いがあります。ここでは、PromiseとAsync/Awaitのパフォーマンスを比較し、それぞれの適切な使いどころについて説明します。

PromiseとAsync/Awaitのパフォーマンス

PromiseとAsync/Awaitのパフォーマンス差は、主に実装やブラウザのエンジンに依存しますが、一般的には以下のような傾向があります。

  • Promise: ネイティブで実装されており、非同期処理のスタックトレースが少ないため、軽量で高速です。多くの非同期操作が連鎖する場合に適しています。
  • Async/Await: 構文的に簡潔で、可読性が高いですが、内部でPromiseを使用しているため、若干のオーバーヘッドがあります。しかし、その違いは微小で、ほとんどのケースで無視できるレベルです。

ベンチマークテスト

以下は、PromiseとAsync/Awaitの簡単なベンチマークテストの例です。これにより、どちらの方が速いかを確認できます。

console.time('Promise');
function fetchDataWithPromise() {
    return fetch('https://api.example.com/data')
        .then(response => response.json())
        .then(data => {
            console.log('Promise Data:', data);
            console.timeEnd('Promise');
        })
        .catch(error => console.error('Promise Error:', error));
}

console.time('Async/Await');
async function fetchDataWithAsyncAwait() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log('Async/Await Data:', data);
        console.timeEnd('Async/Await');
    } catch (error) {
        console.error('Async/Await Error:', error);
    }
}

fetchDataWithPromise();
fetchDataWithAsyncAwait();

このベンチマークは、どちらの方法がより速いかを計測するための単純なテストです。実際の結果は、環境やネットワーク状態により異なるため、両者のパフォーマンスはほぼ同等と考えて良いでしょう。

適切な選択

PromiseとAsync/Awaitのどちらを使用するかは、以下の点を考慮して選択します。

コードの可読性

Async/Awaitは、コードの可読性と保守性を向上させるため、複雑な非同期処理に適しています。一方、Promiseは、単純な非同期チェーンや複数の非同期操作を一度に実行する場合に適しています。

エラーハンドリング

Async/Awaitは、try...catch構文を使用して同期的なエラーハンドリングを行うため、エラーハンドリングが簡単で直感的です。Promiseは、チェーン全体でエラーをキャッチすることができますが、エラーハンドリングが複雑になることがあります。

パフォーマンス

前述の通り、PromiseとAsync/Awaitのパフォーマンス差は微小です。一般的なアプリケーションでは、パフォーマンスの違いはほとんど気にする必要はありません。ただし、極端なパフォーマンスが求められる場合は、簡単なベンチマークテストを実施し、どちらが適しているかを確認すると良いでしょう。

これらの点を考慮し、PromiseとAsync/Awaitの適切な使い分けを行うことで、JavaScriptの非同期処理を効率的に管理し、アプリケーションの性能と可読性を最大限に引き出すことができます。

応用例と演習問題

JavaScriptのPromiseとAsync/Awaitの理解を深めるためには、実践的な応用例と演習問題に取り組むことが重要です。ここでは、いくつかの応用例とそれに基づく演習問題を紹介します。

応用例1:連続したAPIコール

複数のAPIコールを連続して行い、その結果を基にさらに処理を行う例です。

async function fetchUserData(userId) {
    const userResponse = await fetch(`https://api.example.com/users/${userId}`);
    if (!userResponse.ok) {
        throw new Error('ユーザーデータの取得に失敗しました');
    }
    const userData = await userResponse.json();

    const postsResponse = await fetch(`https://api.example.com/users/${userId}/posts`);
    if (!postsResponse.ok) {
        throw new Error('ユーザーポストの取得に失敗しました');
    }
    const userPosts = await postsResponse.json();

    return { userData, userPosts };
}

fetchUserData(1)
    .then(result => {
        console.log('ユーザーデータ:', result.userData);
        console.log('ユーザーポスト:', result.userPosts);
    })
    .catch(error => {
        console.error('エラー:', error);
    });

演習問題1

上記の応用例を基に、ユーザーのコメントも取得するようにコードを拡張してください。取得したコメントはuserCommentsとして返すようにします。

async function fetchUserDataExtended(userId) {
    // ユーザーデータとユーザーポストの取得
    // ここにユーザーのコメントを取得する処理を追加
}

// 結果をコンソールに出力
fetchUserDataExtended(1)
    .then(result => {
        console.log('ユーザーデータ:', result.userData);
        console.log('ユーザーポスト:', result.userPosts);
        console.log('ユーザーコメント:', result.userComments);
    })
    .catch(error => {
        console.error('エラー:', error);
    });

応用例2:ファイルの読み込みと書き込み

Node.js環境で、非同期にファイルを読み込み、内容を変換して新しいファイルに書き込む例です。

const fs = require('fs').promises;

async function readAndWriteFile(inputFilePath, outputFilePath) {
    const content = await fs.readFile(inputFilePath, 'utf-8');
    const transformedContent = content.toUpperCase(); // 内容を大文字に変換
    await fs.writeFile(outputFilePath, transformedContent);
    console.log('ファイルの書き込みが完了しました');
}

readAndWriteFile('input.txt', 'output.txt')
    .catch(error => {
        console.error('エラー:', error);
    });

演習問題2

上記の応用例を基に、ファイルの内容を逆順にして書き込むようにコードを変更してください。

async function readAndReverseWriteFile(inputFilePath, outputFilePath) {
    // ファイルの読み込みと内容の変換
    // ここにファイルの内容を逆順に変換する処理を追加
}

// 結果の確認
readAndReverseWriteFile('input.txt', 'output.txt')
    .catch(error => {
        console.error('エラー:', error);
    });

応用例3:非同期処理のタイマー

一定時間後に非同期処理を実行するタイマーの例です。

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function executeAfterDelay() {
    console.log('タイマー開始');
    await delay(2000); // 2秒待機
    console.log('2秒後に実行');
}

executeAfterDelay();

演習問題3

上記の応用例を基に、5秒ごとに「タイマー実行中」というメッセージを10回出力するコードを作成してください。

async function executeRepeatedly() {
    // タイマーを設定して、メッセージを繰り返し出力
}

// 実行
executeRepeatedly();

これらの応用例と演習問題を通じて、PromiseとAsync/Awaitの使い方をより深く理解し、実際のプロジェクトで効果的に活用できるようになります。

まとめ

本記事では、JavaScriptにおけるPromiseとAsync/Awaitの違いとそれぞれの使い分けについて詳しく解説しました。Promiseは非同期処理を直線的に記述するための基本的な手段であり、エラーハンドリングや並列処理に強みがあります。一方、Async/Awaitは、非同期処理を同期処理のように記述することができ、コードの可読性と保守性を大幅に向上させます。

また、具体的なコーディング例やベストプラクティスを通じて、実際のプロジェクトでこれらの手法をどのように活用すれば良いかについても学びました。エラーハンドリングの重要性や、適切なパフォーマンス比較を行う方法、そして応用例や演習問題を通じて、実践的なスキルを身につけることができたと思います。

PromiseとAsync/Awaitの使い分けを理解し、適切なシチュエーションでこれらを使いこなすことで、より効率的で信頼性の高いJavaScriptの非同期処理を実現することができます。この記事が、あなたの開発プロセスにおいて役立つ知識を提供できたことを願っています。

コメント

コメントする

目次