C#開発者のための最新JavaScript事情(Promise編パート2)特集:C#×JavaScript(1/3 ページ)

今回はPromiseオブジェクトの状態と、Promiseオブジェクトが提供するメソッド、thenableオブジェクトなど、少し高度な話題について見てみよう。

» 2016年01月08日 05時00分 公開
[かわさきしんじInsider.NET編集部]
特集:C#×JavaScript
業務アプリInsider/Insider.NET

powered by Insider.NET

「特集:C#×JavaScript」のインデックス

連載目次

 前回はPromiseオブジェクトを使用した非同期処理の基本について見た。今回はPromiseオブジェクトについてさらに詳しく見ていこう。

Promiseオブジェクトの状態

 Promiseオブジェクトは次の三つの状態を持つ。

  • fulfilled
  • rejected
  • pending

 fulfilledとrejectedは、Promiseオブジェクトが表す非同期処理が完了しており、fulfilledはそれが成功したことを、rejectedは失敗したことを表す。pendingは非同期処理がまだ完了していないことを表す。これらは相互に排他的であり、かつ一度fulfilled状態あるいはrejected状態になったPromiseオブジェクトの状態がそれ以外に遷移することはない。

 これを図に示すと次のようになる。

Promiseオブジェクトの状態 Promiseオブジェクトの状態

 また、pending以外の状態(fulfilledあるいはrejectedのいずれかの状態)のことを「settled」(=fulfilledかsettledのいずれかに落ち着いて変化することがない状態)と呼ぶことがある。

 fulfilled状態のPromiseオブジェクトに対してthenメソッドを呼び出すと、第1引数に指定した関数(=成功時に実行される関数)が呼び出される。rejected状態の場合は、第2引数に指定した関数(=失敗時に実行される関数)が呼び出される。pending状態の場合は、他の二つの状態のいずれかに状態が変化したときに実行される関数のセットアップが行われる。

// new Promise()呼び出しで作成した直後のプロミスはpending状態
var p = new Promise((resolve, reject) => { ... });

…… 省略 ……

p.then(
  function(value)  { ... },  // pがfulfilled状態の場合に呼び出される
  function(reason) { ... }   // pがrejected状態の場合に呼び出される
);

Promiseオブジェクトの状態

 最後にPromiseオブジェクトがfulfilled状態かrejected状態のいずれかになるか、プロミスチェーンによって別のPromiseオブジェクトの状態と関連付けられることを「resolved」(解決された)と呼ぶことがある。

 コンストラクタ呼び出しによって作成された直後のPromiseオブジェクトはpending状態になるが、最初からfulfilled/rejected状態のPromiseオブジェクトを作成するメソッドもある。それが次に見るPromise.resolveメソッドとPromise.rejectメソッドだ。

Promise.resolveメソッドとPromise.rejectメソッド

 Promise.resolveメソッドは、引数に渡した値を完了値として成功した状態のPromiseオブジェクトを返す(引数にPromiseオブジェクトを渡した場合は、そのPromiseオブジェクトが戻り値となる)。これはつまり、以下のPromiseコンストラクタ呼び出しと同じことを意味する。

// 以下の二つのコンストラクタ/メソッド呼び出しは同じ意味
var p1 = new Promise((resolve, reject) => resolve("always resolved"));
var p2 = Promise.resolve("always resolved");

// p1とp2は成功しているので常に第1引数(=resolve関数)が呼び出される
p1.then(
  function(value) { console.log("success: " + value); },
  function(reason) { console.log("fail: " + reason); }
);

p2.then(
  value => console.log("success: " + value),
  reason => console.log("fail: " + reason)
);

Promise.resolveメソッドは成功したPromiseオブジェクトを返す
出力結果は共に「success: always resolved」になる。なお、thenメソッドに引数に渡す関数をp1オブジェクトについては関数式を、p2オブジェクトについてはアロー関数を使用しているが、これらも同じ意味になる。

 これは何かのオブジェクトをPromiseオブジェクト化して、それを使って何らかの処理を行いたいときに活用できる(後述)。

 Promise.rejectメソッドは、引数に渡した値を非同期処理が失敗した理由とするPromiseオブジェクトを返す。Promise.resolveメソッドと対称的に、こちらは以下のコンストラクタ呼び出しと同じことを意味する。

// 以下の二つのコンストラクタ/メソッド呼び出しは同じ意味
var p1 = new Promise((resolve, reject) => reject("always rejected"));
var p2 = Promise.reject("always rejected");

// p1とp2は失敗しているので常に第2引数(=reject関数)が呼び出される
p1.then(
  function(value) { console.log("success: " + value); },
  function(reason) { console.log("fail: " + reason); }
);

p2.then(
  value => console.log("success: " + value),
  reason => console.log("fail: " + reason)
);

Promise.rejectメソッドは失敗したPromiseオブジェクトを返す
出力結果は共に「fail: always rejected」になる。

 常に失敗した(rejected状態の)Promiseオブジェクトが戻り値となるので、通常時にはあまり使い道はないだろうが、テスト/デバッグ用途で使えると思われる。

 次に前回説明したPromise.allメソッドと対になるPromise.raceメソッドについて簡単に見ておこう。

       1|2|3 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。