言語によってちょっと違うFuture/Promiseをまとめてみた(2) 

# 続き

[前回](http://qiita.com/reki2000/items/6acf94a07dee8d26a744)はJava5、Java8、Play1Java についてFuture周りの仕様と使い方をなぞりました。

Play2Java、RxJava あたりも見ていきたいのですが、少し気分を変えるために今回は JavaScript を見ていくことにします。

# JavaScript(ECMAScript6)

### 参考記事

こちらの記事に知りたいことがほとんど全部書いてありました……

* [JavaScript Promises - There and back again](http://www.html5rocks.com/ja/tutorials/es6/promises/) 
* [[JS]JavaScriptにおけるPromise/A+仕様を、チュートリアル形式で詳しく解説します](http://www.yoheim.net/blog.php?q=20140310)
* [あなたが読むべきJavaScript Promises](http://jser.info/post/77696682011/es6-promises/)
* [②ality – JavaScript and more](http://www.2ality.com/2014/10/es6-promises-api.html)


### Promises/A+

[Promises/A+](https://github.com/promises-aplus/promises-spec) というJavaScript標準仕様がある。抜粋すると：

  * "Promise" とは `then` メソッドを持つオブジェクトまたは関数のこと
  * このような関数を "thenable" と呼ぶ
  * Promise は pending, fulfilled, rejected のいずれかの状態をとり、不変である
  * `then` は onFulfilled と onRejected の2つのコールバック関数をとり、いずれかがただ一度だけ呼ばれる。
  * `then` は 各コールバック関数の結果を値とする次の `Promise`を返す

### どうやって Promise を生成するのか?

仕様では具体的な生成の方法は定めておらず、APIによって少しずつやり方が異なるとのこと。

ECMAScript6でのコード例は以下のようになります。

```js
var promise = new Promise(function(resolve, reject) {
  ... // 重い処理
  if (success) {
     resolve(result);
  } else {
     reject(error);
  }
});

promise.then(
  function(result) { ... }, // 正常終了時の処理
  function(error)  { ... }  // エラー発生時の処理
).then(
  function(error)  { ... }  // 正常系だけを書ける
).catch(
  function(error) { ... }   // "catch" でエラー処理だけを書ける
)
```

メインの重い処理は then が呼ばれるまで動かない（中でsetTimeout()して非同期で動くようになっているらしいが未確認）。


Java だとコールバック登録してからスレッド与えて起動、というイメージのAPIでしたが、JavsScript ではコールバック登録したら処理開始を許す、というイメージですね。

### タイムアウト

以下のようにタイムアウトしたら`reject`する`Promise`を作るというアプローチ。ちょっと煩雑……

```js
 function timeout(ms, promise) {
        return new Promise(function (resolve, reject) {
            promise.then(resolve);
            setTimeout(function () {
                reject(new Error('Timeout after '+ms+' ms')); // (A)
            }, ms);
        });
    }
```

### Promise の合成

* すべての終了を待つのは `Promise.all(promise_list)`
* 一つだけ待つのは `Promise.race(promise_list)`

# jQuery.Deferred

こちらを参考にさせいもらいました

* [爆速でわかるjQuery.Deferred超入門](http://techblog.yahoo.co.jp/programming/jquery-deferred/)
* [jQuery.Deferredを使って楽しい非同期生活を送る方法](http://qiita.com/yuku_t/items/3d1cf51d7ae91305eaaa)

### 概要

* `jQuery.Deferred` は jQuery独自の `Promse` を扱うためのオブジェクト。
* `Promise` を生成したのち `then` を使う分には、Promises/A+ とほぼ同じ使い方ができる。
  * then の動作が標準にそろえられたのは jQuery 1.8 から。 [本家API - deferred.then()](http://api.jquery.com/deferred.then/)
* 元々は`.then(A,B)` ではなくて `.done(A)`（正常終了）、`.fail(B)`（エラー処理）という名前でチェーンしていた
* `.always()` で最後に必ず呼びたい処理を書ける
* `Promise` の生成の仕方が ECMAScript6 とちょっと違う

### 元々Deferred対応しているAjax関数などを使う

jQuery のAjax関数群は Promiseを返すようになっており、そのまま thanable 的に使える

```js
$.get('...').then(function(result) {
  ...
})
```


### 自分で Promise を作る

Promise が内部で自分の親 Deferred を参照していて、その親のスコープにある重い処理本体までたどれるというつくりになっている

```js
function myPromise() {
  var d = $.Deferred();
  setTimeout(function() {
    // 重い処理
    if (success) {
      d.resolve(result);
    } else {
      d.reject(error);
    }
  }, 1000);
  return d.promise();
}
```

### 並列実行

* `when` に `Promise` を複数渡せば並列実行できる。"all"的なもの。一つでも失敗すると全体としてエラー扱い
* "any" 的なものはなさそう

```
$.when(promise1, promise2, ...)
  .done(function(result1, result2, ...) { ... });
```


# 続く

少しずつ全体感が見えてきたように思います。引き続き Scala編に行ってみます。生きて帰りたい