LoginSignup
29
28

More than 5 years have passed since last update.

プロミス処理のラッパーをつくる。

Last updated at Posted at 2015-09-02

UPDATE 「即時関数」って連呼してたけど、非同期処理に対する同期処理の意味だった。言葉間違えてました!

jQueryDeferred オブジェクトで Promise の実装をしていて、Deferred オブジェクト生成部分を共通化したくなったので、高階関数化して同期処理を Promise に変換する関数をつくってみた。

// Underscore.js と jQuery が必要。

var promisify = function (func) {
  var funcPartial = function () {
    var funcArgs = _.toArray(arguments);
    var dfr = new $.Deferred(), promiseArgs = [ dfr.resolve, dfr.reject ];
    var timeoutId = setTimeout(function () {
      clearTimeout(timeoutId);
      func.apply(undefined, _.union(promiseArgs, funcArgs));
    }, 1);
    return dfr.promise();
  };
  return funcPartial;
};

これを使うと例えば;

// 画像プリロードをする処理を上記高階関数内で定義して;
var imageLoaded = promisify(function (resolve, reject, url) {
  return $(document.createElement('img'))
  .on('load', resolve)
  .on('error', reject)
  .attr('src', url);
});

// 画像プリロード結果を返す Promise を生成できる。
imageLoaded('http://lorempixel.com/400/200/');
.then(function (ev) {
  var $el = $(ev.target), width = $el[0].naturalWidth, height = $el[0].naturalHeight;
  console.log('完了!', width, height);
}, function (err) {
  console.error('エラー!', err.message);
})

この高階関数 promisify を使って関数を定義すれば、単純な値から同期処理、イベント等全ての処理を、非同期処理として Promise を返すようにできる。

また、Deferred オブジェクトの生成過程をカリー化して集約しているので、jQuery の Deferred オブジェクトから QES6 の Promise に変更したい時も、関数一つ修正すれば、全ての Promise の内部処理を入れ替えられる。

かなり便利! だと思う。

29
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
28