JavaScriptのPromiseで非同期処理を扱う

JavaScriptのPromise関数の役割

JavaScriptのPromise関数は、非同期処理を扱うためのオブジェクトです。
Promiseを使用することで、非同期処理の結果を待つことができ、その結果が成功か失敗かに応じて適切な処理を行うことができます。
async/awaitでも同じようなことができますので、async/awaitとの違いも後述します。
まずはPromise関数の主要な役割と基本的な使い方について説明します。

Promiseの基本的な役割

1. 非同期処理の管理:
Promiseは、非同期処理の完了を待つための手段を提供します。
例えば、ネットワークリクエスト、ファイルの読み書き、タイマーなどの非同期操作の結果を処理する際に使用されます。

2. コールバック地獄の回避:
非同期処理をコールバック関数だけで管理すると、ネストが深くなりやすく、コードの可読性が低下します。
Promiseを使うことで、ネストを避け、チェーンの形で処理を記述できます。

3. エラーハンドリングの統一:
Promiseは、非同期処理の成功と失敗の両方を一元的に管理する方法を提供します。
これにより、エラー処理が簡単になります。

Promiseの基本的な使い方

Promiseの作成

Promiseはnew Promiseコンストラクタを使用して作成します。
コンストラクタは引数として、resolveとrejectという2つの関数を持つコールバック関数を受け取ります。

const myPromise = new Promise((resolve, reject) => {
    // 非同期処理をここで行う

    if (success) {
        resolve("処理が成功しました");
    } else {
        reject("処理が失敗しました");
    }
});
Promiseの使用

Promiseが返されると、それに対してthenやcatchメソッドを使って非同期処理の結果をハンドリングできます。

myPromise
    // myPromiseの引数のresolveにあたる
    .then((result) => {
        console.log(result); // "処理が成功しました" と表示される
    })
    // myPromiseの引数のrejectにあたる
    .catch((error) => {
        console.log(error); // "処理が失敗しました" と表示される
    });
Promiseのチェーン

複数の非同期処理を順番に行う場合、Promiseをチェーンさせて記述できます。

const firstPromise = new Promise((resolve, reject) => {
    resolve("最初の処理が成功しました");
});

firstPromise
    .then((result) => {
        console.log(result);
        return new Promise((resolve, reject) => {
            resolve("次の処理も成功しました");
        });
    })
    .then((result) => {
        console.log(result);
    })
    .catch((error) => {
        console.log(error);
    });

async/awaitとの違い

Promiseとasync/awaitはどちらもJavaScriptで非同期処理を扱うための仕組みですが、async/awaitはPromiseをより簡潔に書くための構文です。
以下に、Promiseとasync/awaitの違いと、async/awaitの使い方について説明します。

Promiseとasync/awaitの違い

Promiseの使用例
function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("データが取得されました");
        }, 2000);
    });
}

fetchData()
    .then(data => {
        console.log(data); // データが取得されました
        return fetchData();
    })
    .then(data => {
        console.log(data); // データが取得されました
    })
    .catch(error => {
        console.error("エラー:", error);
    });
async/awaitの使用例
async function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("データが取得されました");
        }, 2000);
    });
}

async function getData() {
    try {
        const data1 = await fetchData();
        console.log(data1); // データが取得されました
        const data2 = await fetchData();
        console.log(data2); // データが取得されました
    } catch (error) {
        console.error("エラー:", error);
    }
}

getData();

主な違い

1. コードの可読性:

  • Promiseを使った場合、thenチェーンが長くなると、ネストが深くなり可読性が低下する可能性があります。
  • async/awaitを使うと、非同期コードが同期コードのように書けるため、可読性が向上します。

2. エラーハンドリング:

  • Promiseでは、catchメソッドを使ってエラーハンドリングを行います。
  • async/awaitでは、通常のtry/catch構文を使ってエラーハンドリングを行います。

3. 非同期処理の連鎖:

  • Promiseを使った場合、次の非同期処理は前の処理のthenの中で呼び出します。
  • async/awaitでは、awaitキーワードを使って非同期処理が完了するのを待ちます。そのため、次の行に次の非同期処理を書けます。

Promiseとasync/awaitはどちらも非同期処理を扱うための強力なツールですが、async/awaitを使うことでコードの可読性が向上し、より直感的に非同期処理を記述できるようになります。