やまろぐはてな

yamanokuの技術メモ。Qiitaは怖くて書けない。

Promise処理について雑にまとめる

Promiseとは

簡単に言うと非同期処理を行う時にコールバック地獄、ネストの深層化を回避して記述をだいぶ楽にするオブジェクト。ES2015です。

非同期処理とは

例えばAの処理の後にBの処理があるとする。javascriptとはシングルスレッドで動く同時に処理を行うということができないものなので、通常であればA、Bの処理で動く。その辺の順番を変えて処理を行うのを非同期処理という。

分かりやすい例はApiと連携するAjax通信を受け取ったレスポンス(200とか404とか)の結果によって処理を行うやつ。

非同期処理の例

例 – ajax通信後順番に処理を行う

var fetchSomething1 = function(done) {
  // API1にアクセス
  doAjaxStuff(someOptions, {
    success: function(data) {
      done(); // 成功したら渡されたfunctionを実行
    }
  });
};

// fetchSomething1と同じようにそれぞれ別のAPIにアクセスするfunction群
var fetchSomething2 = function(done) { /* 省略 */ };
var fetchSomething3 = function(done) { /* 省略 */ };
var fetchSomething4 = function(done) { /* 省略 */ };

var doSomethingFinally = function() {
  // APIにアクセスして取得してきたデータを使って何かする
};

こういう関数を登録しておき、順番に処理を行うとする。通常だと

fetchSomething1(function() {
  fetchSomething2(function() {
    fetchSomething3(function() {
      fetchSomething4(doSomethingFinally);
    });
  });
});

こうなるが、これが

fetchSomething1()
  .then(fetchSomething2)
  .then(fetchSomething3)
  .then(fetchSomething4)
  .then(doSomethingFinally);

こうなる。コールバック地獄、ネスト深層化問題の回避がよく分かる。

// Callback
fetchSomething1(function() {
  fetchSomething2(function() {
    fetchSomething3(function() {
      fetchSomething4(doSomethingFinally, function() {
        // fetchSomething4のエラー処理
      });
    }, function() {
      // fetchSomething3のエラー処理
    });
  }, function() {
    // fetchSomething2のエラー処理
  });
}, function() {
  // fetchSomething1のエラー処理
});

// Promise then & catch
fetchSomething1()
  .then(fetchSomething2)
  .catch(/* fetchSomething1のエラー処理 */);
  .then(fetchSomething3)
  .catch(/* fetchSomething2のエラー処理 */);
  .then(fetchSomething4)
  .catch(/* fetchSomething3のエラー処理 */);
  .then(doSomethingFinally)
  .catch(/* fetchSomething4のエラー処理 */);

エラー処理も含めると更に分かりやすくなる。こういう風に書くと見やすくなってメンテナンス性も上がりますね。

ブラウザ対応状況 – CanIUse

f:id:cardboarder:20170528175745p:plain

発表されてからだいぶ時間が経ったのでブラウザ対応であれば、現状IE11以外だったら大丈夫。

パフォーマンス対決

jsPrefにて計測。

Promise vs Callback

f:id:cardboarder:20170528202919p:plain

Native Promise vs Callback

f:id:cardboarder:20170528202638p:plain

非同期処理だとそこまで差はないけどそのまま使うPromiseだと圧倒的にCallbackのがパフォーマンス良い。素で使わないほうがよさそう。

おまけ – Promise と async/await のイメージについて

このGifが一番イメージしやすい。

参考