JavaScriptのPromiseでコールバック関数を置き換える

Code Html Computer Internet It  - RoonZ-nl / Pixabay プログラミング
RoonZ-nl / Pixabay
スポンサーリンク

よくわからないまま放置していたPromiseがとても便利でした。基本的なことですが、備忘録。

関数の処理が終わったら何かしたい

昔ながらのコールバック関数をずっと使い続けていました。例えば500ms経過したら成功か失敗を返すhoge関数があるとします。

コールバック関数

function hoge(cb = null) {
  setTimeout(() => {
    if (Math.random() < 0.5) {
      cb('成功');
    } else {
      cb('失敗');
    }
    cb(true);
  }, 500);
}

hoge((result) => console.log(result));

引数にcallback関数を渡す場合はこのようになると思います。一応これでも動きますが、どうも泥臭い感じになってしまいます。

Promise

function hoge() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() < 0.5) {
        resolve('成功');
      } else {
        reject('失敗');
      }
    }, 500);
  });
}

hoge()
  .then((result) => console.log(result))
  .catch((error) => console.error(error));

同じ処理をPromiseに置き換えたものがこちら。

new Promiseを返すことで、コール側が非同期処理を制御できます。resolveは成功、rejectは失敗のコールバックと同じです。resolve は then で受け、reject は catch で受けます。

thenで成功、catchで失敗の処理を明示できているのもわかりやすくて良いです。

Promise.allでPromiseをまとめて処理する

Promiseはオブジェクトなので、まとめて扱うこともできます。

Promise.allでの実行

const promises = [];
for (let i=0; i<2; i++) {
  promises.push(new Promise((resolve, reject) => {
    setTimeout(() => {
      Math.random() < 0.5 ? resolve(`成功:${i}`) : reject(`失敗:${i}`);
    }, 500 * Math.random());
  }));
}

Promise.all(promises)
  .then((result) => console.log(result))
  .catch((error) => console.error(error));

Promise.allの場合、どれか1つでも reject すると catch() しか呼ばれません。すべて resolve の場合のみ then() が呼ばれます。

上の例の場合、2つのPromiseをまとめて実行し、結果は以下の3パターンどれかになります。

"失敗:0"
"失敗:1"
["成功:0", "成功:1"]

Promise.allでrejectがあった場合の実行結果

reject の場合、最初に reject になった結果のみが返されます。

1つ目が失敗なら”失敗:0″、2つ目が失敗なら”失敗:1″だけが返り、他の結果はわかりません。

Promise.allでrejectがない場合の実行結果

reject がなく、すべて resolve の場合は配列で結果が返ります。配列内の順序は resolve を呼び出した順番ではなく、Promise.all()の引数の順番です。

    setTimeout(() => {
    }, 500 * Math.random());

上の例ではこのように完了タイミングをランダムにしていますが、成功の場合は常に [“成功:0”, “成功:1”] です。

[“成功:1”, “成功:0”] という順序で返ることはありません。

まとめ

とりあえず使ってみることが大事。

スッキリすると保守性も上がって気分も良いです。

タイトルとURLをコピーしました