8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

プロミスについて整理したことのまとめ

Posted at

Learning ECMAScript6 が参考書籍

Promise はモナド

計算中かもしれない値を管理する文脈を持つモナド。
非同期操作を依存関係に従ってパイプライン化することでネストや処理の分離をなくし、コールバックやイベントを用いたコードよりも可視化性を高める。

プロミスはモナドである認識を持つことにより、多少 Haskell の知識がある自分としては、プロミスの必要性や位置付けを理解しやすくなった。

以降は、プロミスの仕様とメソッドの例などを整理している。

The Promise Constructor

Promise コンストラクタは、Promise オブジェクトを作るために使われる。 Promise オブジェクトは非同期操作を表現するオブジェクト。

Promise コンストラクタには executor と呼ばれるコールバック関数を渡し、このexecutor にはresolverejectの二つのコールバック関数を渡す。

resolve/rejectの実態は、その後then()で渡される処理が合成されたもの?なので、プログラマが明示的にこれらの関数を直接実装することはない。

プロミスのステータス

プロミスオブジェクトのステータスは、次のように分類される。

status description
Fulfilled resolve関数が、non-promise なオブジェクトとともに呼び出された時
Rejected reject関数が呼び出されたり、executor のスコープで例外が発生した時
Pending resolverejectがまだ呼び出されていない状態
Settled Pending ではない時(ref)

Once a Promise is fulfilled or rejected, it cannot be transitioned back. An attempt to transition it will have no effect.
一度 Fulfilled または Rejected になると、その状態を戻すことはできない。やろうとしても、何も起きない。

プロミスの特徴として、resolve関数に Promise オブジェクトが渡った場合、元のオブジェクトのステータスは渡されたオブジェクトのステータスに依存することになる。

// プロミスにプロミスを渡す
let a = new Promise(function (resolve, reject) {
  let b = new Promise(function (res, rej) {
    setTimeout(function () {
      res(100);
    }, 1000);
  });
  resolve(b);
});

a
  .then(function (value) {
  console.log('the value fulfilled is ' + value);
  return value * 3; // return the value multiplied 3
})
  .then(function (value) {
    console.log('the value passed by previous then is :' + value);
  });

The then(onFulfilled, onRejected) method

The callbacks passed to the then() method are executed asynchronously.
thenに渡されるコールバック関数は非同期処理となる。

The then() method always returns a new promise object, which resolves the return value of the calling callback.
thenは必ず promise object を返し、このオブジェクトは渡されたコールバック関数がreturnした値をresolveする。

The catch(onRejected) method

then(null, onRejected)のシンタックスシュガー。

promise.then(null, function(reason){
});
promise.catch(function(reason){
});

catchも promise object を返し、、このオブジェクトは渡されたコールバック関数がreturnした値をresolveする。つまり、さらにthenよるチェーンを作ることができる。

let a = new Promise(function (resolve, reject) {
  let b = new Promise(function (res, rej) {
    setTimeout(function () {
      rej(100);
    }, 1000);
  });
  resolve(b);
});

a
  .then(function (value) {
  console.log('the value fulfilled is ' + value);
  return value * 3; // return the value multiplied 3
})
  .catch(reason => {
    console.log('error : ' + reason);
    return reason;
  })
  .then(value => { // チェーン可能。onRejectの返り値を引数にとっている
    console.log('re:value: ' + value);
  });

モナドっぽい雰囲気

普通の値を、プロミスという文脈に包む関数が用意されている。

The Promise.resolve(value) method

The resolve() method is basically used to convert a value to an promise object. It is useful when you find yourself with a value that may or may not be a Promise, but you want to use it as a Promise.For example, the jQuery Promises have different interfaces than the ES6 Promises. Therefore, you can use the resolve() method to convert the jQuery Promises into the ES6 Promises.
これから使おうとしている値が promise object かどうかわからない時、これを使うとプロミスで包むことができる。

The Promise.reject(value) method

主にデバッグ目的で利用する。値をプロミスで包むため、という使われ方はしない。

The Promise.all(itearable) method

iterable オブジェクトの中の promise object が全て fulfill されると、このpromise object も fulfill される。

The Promise.race(iterabe) method

The the race() method of the Promise object takes an iterable object as the argument and returns a Promise that fulfills or rejects as soon as one of the Promises in the iterable object is fulfilled or rejected, with the fulfillment value or reason from that Promise.

iterable オブジェクトの中の promise object のうち、最も早く settled となったオブジェクトが返る。以降、その他のオブジェクトも raceの制御とは無関係にresolve されていく。

let p1 = new Promise(function(resolve, reject){
  setTimeout(function(){
    resolve("Fulfillment Value 1");
  }, 1000);
});

let p2 = new Promise(function(resolve, reject){
  setTimeout(function(){
    reject("fulfillment Value 2");
  }, 2000);
});

var arr = [p1, p2];

Promise.race(arr).then(function(value){
  console.log('onFulfilled: ' + value); //Output "onFulfilled: Fulfillment Value 1"
}, function(reason){
  console.log('onRejected: ' + reason);
});

8
9
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
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?