Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

goog.Promise の使い方

日本語情報少ないので。

Promiseとは?

こちらをご覧ください。

Promiseオブジェクトを作る

newを使ってコンストラクタを呼ぶだけです。このとき、引数に関数をひとつ渡してやる必要があります。この関数はresolve関数とreject関数を受け取るので、関数内で

  • 処理成功時は resolve
  • 処理失敗時は reject

を呼んでやる必要があります。それぞれ引数に値をひとつ渡すことができ、他の処理に結果を受け渡すことができます。

var promise = new goog.Promise(function (resolve, reject) {
  if (...) {
    resolve(result);
  } else {
    reject(err);
  }
});

コンストラクタ引数は無名関数ではなく、メソッドあるいはローカルな関数として定義しても良いですね。公式ドキュメントではresolverと命名されています。

function resolver(resolve, reject) {
  if (...) {
    resolve(result);
  } else {
    reject(err);
  }
}

var promise = new goog.Promise(resolver);

成功時の処理を書く

var promise = new goog.Promise(resolver);
promise.then(function(result) {
  // resolve() の引数に渡した値をここで使える
  console.log(result);
});

失敗時の処理を書く

var promise = new goog.Promise(resolver);
promise.thenCatch(function(err) {
  // reject() の引数に渡した値をここで使える
  console.log(err);
});

必ず実行したい処理を書く

var promise = new goog.Promise(resolver);
promise.thenAlways(function() {
  // リソース解放など
});

合わせ技

then などのメソッドは自分自身を戻り値として返すので、メソッドチェーンが可能です。

var promise = new goog.Promise(resolver)
  .then(displayDialog)
  .thenCatch(displayAlert)
  .thenAlways(unlockSubmitButton);

Promiseの合成

静的メソッドとして、以下3種類が用意されています。

  • goog.Promise.all(promises)
  • goog.Promise.firstFulfilled(promises)
  • goog.Promise.rase(promises)

allはすべてresolveされた時のみresolveされるものです。thenにはすべてのPromiseの結果が配列に入れられて返ります。必要なリソースを並列で用意するときに利用できるでしょう。ES6のやつと同じです。

goog.Promise.all(assetLoader, dataLoader, calculator)
  .then(function(result) {
    var asserts = result[0];
    var data = result[1];
    var computed = result[2];
    doFoo(asserts, data, computed);
  });

firstFullfilledは、最初にresolveされた結果を返します。ひとつでもresolveされたら合成後のPromiseはresolvedになります。すべてrejectされたときのみrejectとなり、thenCatchが呼び出されます。同じ資源を複数の経路で準備できる際など、ひとつでも成功すれば良い・最も早く取得できた結果を使えれば良い時に利用できるでしょう。

goog.Promise.firstFullfilled(loadDataFromCDN, loadDataFromServer)
  .then(function(data) {
    doFoo(data);
  });

raseは最初にresolve/rejectされたPromiseの結果を返します。ES6のやつと同じです。

goog.resultとgoog.async.Deferred

これらは非推奨と明記されています。新規の利用は控えましょう。

  • NOTE: goog.result is soft deprecated - we expect to replace this and
  • {@link goog.async.Deferred} with {@link goog.Promise}.