🦊

JavaScript Promiseについて

2024/01/25に公開

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

🍯Promiseとは

JavaScriptPromiseオブジェクトは、非同期作業の完了または失敗を表すオブジェクトです。これにより、非同期作業を容易に扱うことができます。
Promiseはコールバック関数の代わりに使用でき、ネストされたコールバック関数の複雑さを減らすことができます。Promiseを使用すると、非同期作業の結果を待ち、その結果に応じて次の作業を連鎖的に実行することができます。
.then()メソッドを使用して履行状態の結果を処理し、.catch()メソッドを使用して拒否状態のエラーを処理します。

function test() {
    return new Promise(function(resolve, reject) {
        $.ajax({
            url: '...',
            data: '...',
            type: 'post',
            success : function(response) {
                resolve(); //通信成功 resolve()
            },
            error: function(error) {
                reject(new Error('通信失敗'));  //通信失敗 reject()
            }
        }); 
    });
}

//成功関数
function testSuccess() {
    console.log("成功");
}

test()            //test 実行
.then(testSuccess) //test 成功したら成功関数実行
.catch(console.error); //test 失敗

test( )を実行し、処理が成功した場合はtestSuccess( )を実行します。この過程で処理に失敗が発生した場合は、catch(console.error)が出力します。

🍯Promise's states

  • 保留(Pending)
  • 履行(Fulfilled)
  • 失敗(Rejected)

🍮保留(Pending)

Promiseが作成されたばかりで、まだ処理が完了していない状態です。

🍮履行(Fulfilled)

非同期コードが成功裏に実行された状態です。

🍮失敗(Rejected)

失敗した状態、エラーが発生した状態です。

🍯Promiseエラー処理

Promiseのエラーを処理する方法は、then()を2回使用するか、catch()を使用してreject()メソッドが呼び出されて失敗状態になった場合です。可能な限りcatchを使用すべきです。その理由は、thenで処理しようとすると、コールバック関数内で発生するエラーを捕捉できないからです。

getData().then(function(result){
    console.log(result);
}).catch(function(err){
    console.log('error : ', err);
});

🍯Promise Static methods

🍮Promise.resolve()、Promise.reject()

Promiseを作成した後、すぐに成功したり失敗したりするresolveやrejectを示すことができます。

function kitchen(order) {
  return Promise.resolve(`${order}=> 🍝`);
}

function table(vegetable) {
  return Promise.resolve(`${vegetable}=>🥗`);
}

function door() {
  // return Promise.resolve(`👨‍👩‍👧‍👦`);
  // return Promise.reject(new Error("お客さんがいません"));
}

door()
  .then((people) => {
    return table(people);
  })
  .then((order) => kitchen(order))
  .then((tablesetting) => console.log(tablesetting))
  .catch((error) => console.log(error));

resolveの場合

rejectの場合

🍮Promise.all()

function getSusi() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("🍣");
    }, 1000);
  });
}
function getOcha() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("🍵");
    }, 3000);
  });
}

function getCookie() {
  return Promise.reject(new Error("no cookie"));
}

getSusi() //
  .then((susi) =>
    getOcha() //
      .then((ocha) => [susi, ocha])
  )
  .then(console.log);

このように呼び出すと、寿司が1秒、お茶が3秒かかるため、合計で4秒かかります。しかし、allを使用すると、並行して実行することができます。

Promise.all([getSusi(), getOcha()]) //
  .then((susiya) => console.log("all", susiya));

並行して開始するため、かかる時間は合計で3秒になります。

🍮Promise.race()

与えられたPromiseの中で最も早く実行されたものが出力されます。

Promise.race([getSusi(), getOcha()]) //
  .then((menu) => console.log("race", menu));

Promise.allSettled()

Promise.all([getSusi(), getOcha(), getCookie()])
  .then((susiya) => console.log("all-error", susiya))
  .catch(console.log);

Promise.all()でエラーが発生した場合、エラーがあるため出力されません。

エラーがある場合はallSettledを使用します。失敗しても成功しても、結果を配列にまとめて表示します。

Promise.allSettled([getSusi(), getOcha(), getCookie()])
  .then((susiya) => console.log("all-error", susiya))
  .catch(console.log);

結論

Promiseの状態、エラー処理方法、そして静的メソッドに関する深層的な分析を通じて、非同期プログラミングの複雑さを解決するのにいかに強力なツールであるかを理解することができました。
個人的に、Promiseは非同期コードをより明確にし、管理しやすくするものであり、特にPromise.allSettledのようなメソッドはさまざまな状況で有用に使えると思います。

Discussion