[JavaScript] JavaScript Promise 入門

Promise の理解が足りないので復習用にまとめておく。

Promise 以前・以後

Promise 前

  • 非同期処理を行いたい場合、function の受け渡しをを利用して実現されてきた。
  • なにかしらの処理が完了したら渡した function を実行させるという実装手法は、「コールバック」と呼ばれる。
  • JavaScriptには、非同期処理をより柔軟に行える機能が求められてきた。

Promise 後

  • Promise を使えば、実行と完了に遅延がある処理をうまい具合に扱うことができる。
  • Promise を利用すれば、非同期処理の書き方を統一できる。

各ブラウザの対応状況と Polyfill

ブラウザのサポート状況は下記で確認できる。

IE は未対応なため、ブラウザポリフィルを利用して対応する。

Promise オブジェクトの基本

Promise オブジェクトを利用する場合、非同期処理を関数としてまとめておく。
関数の戻り値が Promise オブジェクトになる。

'use strict';
require('babel-polyfill');
/**
 * @param {String} value
 * @return {Promise}
 */
function asyncProcess(value) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (value) {
        resolve(`入力値: ${value}`);
      } else {
        reject('入力値は空です。');
      }
    }, 500);
  });
}

resolve 関数で成功を、reject 関数で失敗が通知されるのでこれを利用する。

then メソッドによる非同期処理の連結

then メソッドで Promise オブジェクトの結果を受け取る。

Promise.prototype.then() – JavaScript | MDN

then メソッドの配下で新たな Promise オブジェクトを返すことで、複数の非同期処理を連結できる。

asyncProcess('菊次郎')
.then(
  (response) => {
    console.log(response);
    return asyncProcess('さき');
  }
)
.then(
  (response) => {
    console.log(response);
  },
  (error) => {
    console.error(`エラー: ${error}`);
  }
);

then の onRejected ハンドラは、Promise オブジェクトが rejected になったときに実行される。
then に onRejected ハンドラが指定されていない場合、後続する then の onRejected ハンドラが実行される。

catch メソッドで失敗処理をまとめて扱う

Promise には、エラー処理だけを個別に書ける catch メソッドが用意されている。

Promise.prototype.catch() – JavaScript | MDN

前述のコードは下記に書き換えられる。

asyncProcess('菊次郎')
.then(
  (response) => {
    console.log(response);
    return asyncProcess('さき');
  }
)
.then(
  (response) => {
    console.log(response);
  }
)
.catch(
  (error) => {
    console.error(`エラー: ${error}`);
  }
);

複数の非同期処理を並列実行する

Promise.all メソッドは、複数の非同期処理を並列に実行し、 そのすべてが成功した場合 に処理を実行する。

Promise.all() – JavaScript | MDN

Promise.all([
  asyncProcess('菊次郎'),
  asyncProcess('さき'),
  asyncProcess('たけし'),
])
.then(
  (response) => {
    console.log(response);
  }
)
.catch(
  (error) => {
    console.error(`エラー: ${error}`);
  }
);

Promise.race メソッドは、複数の非同期処理を並列に実行し、 いずれか1つが最初に完了したところで 成功コールバックを呼び出す。
結果は変化する可能性がある。

Promise.race() – JavaScript | MDN

Promise.race([
  asyncProcess('菊次郎'),
  asyncProcess('さき'),
  asyncProcess('たけし'),
])
.then(
  (response) => {
    console.log(response);
  }
)
.catch(
  (error) => {
    console.error(`エラー: ${error}`);
  }
);

参考文献

この2つを繰り返し読みたい。

以下の記事が、日本語で読めなくなっている。
こちらにリダイレクト。日本語の原稿

読みづらいので後でまとめる。

補遺

Node.js のサンプルコード。

Generator と Promise を組み合わせることで非同期処理を同期処理のように直列に書くことができる。

Promise に async / await を組み合わせて書く方法。