検索
特集

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

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

Share
Tweet
LINE
Hatena

Promise.raceメソッド

 前回見たPromise.allオブジェクトは、「配列などに格納した複数のPromiseオブジェクトの全てが完了すること」を表すPromiseオブジェクトを返す。全てのプロミスが完了するのを待機し、それぞれの完了結果を配列の要素として取り扱える。

 Promise.raceメソッドも配列などに格納された複数のPromiseオブジェクトを受け取り、新たなPromiseオブジェクトを返すが、Promise.allメソッドとは異なり、複数のPromiseオブジェクトのいずれかが完了した時点で、新たなPromiseオブジェクトも完了する。

 以下に例を示す。

var promiselist = [
  new Promise(
    (resolve, reject) => setTimeout(() => resolve("promise0"), 500)
  ),
  new Promise(
    (resolve, reject) => setTimeout(() => resolve("promise1"), 100)
  ),
  new Promise(
    (resolve, reject) => setTimeout(() => resolve("promise2"), 1000)
  )
];

Promise.race(promiselist).then(
  value  => console.log("resolve: " + value),
  reason => console.log("reject: " + reason)
);

Promise.raceメソッド

 ここでは三つのPromiseオブジェクトを要素とする配列を作成して、それをPromise.raceメソッドに渡している。要素となるPromiseオブジェクトではsetTimeout関数を使って、それぞれのプロミスが完了するタイミングに差を付けている。

 このコードを実行すると次のようになる。

>node --harmony promisetest.js
resolve: promise1


いずれかのPromiseオブジェクトが完了した時点で、Promise.raceメソッドが返すPromiseオブジェクトも完了する

 なお、上の実行結果では分からないのだが、プロンプトが表示されて、コンソールへの入力が可能になるまでには少し時間がかかる。これはPromise.raceメソッドが返すPromiseオブジェクトは完了しても、もともとの配列に格納されていたPromiseオブジェクトの実行は続けられるためだ。上のコードを少し変更して試してみると、このことが分かる。

var promiselist = [
  new Promise(
    (resolve, reject) => setTimeout(() => {
      console.log("promise0");
      resolve("promise0");
    }, 500)
  ),
  …… 省略 ……
];

Promise.race(promiselist).then(
  value  => console.log("resolve: " + value),
  reason => console.log("reject: " + reason)
);

Promise.raceメソッドが返すPromiseオブジェクトが完了しても、配列の各要素の実行は続けられる

 ここでは最初の要素が完了したときに、コンソールに出力するように変更している。このコードの実行結果は次のようになる。

>node --harmony promisetest.js
resolve: promise1
promise0


Promise.raceメソッドが返すPromiseオブジェクトが完了しても、配列の各要素の実行は続けられる

 このように、最初に実行が完了しなかったPromiseオブジェクトについても、その完了時にコンソールにメッセージを表示している。

 余談ではあるが、Promise.allメソッドに渡した複数のPromiseオブジェクトのいずれかが失敗したときにはどうなるだろう。上のコードを再度改変して、少し試してみよう。

var promiselist = [
  new Promise(
    (resolve, reject) => setTimeout(() => reject("promise0"), 500)
  ),
  …… 省略 ……
];

Promise.all(promiselist).then(
  value  => console.log("resolve: " + value),
  reason => console.log("reject: " + reason)
);

Promise.allメソッドが待機する全てのPromiseオブジェクトの中でrejectされるものが出た場合

 ここでは最初の要素でタイムアウト発生後にreject関数を呼び出している(失敗)。この場合、実行結果は次のようになる。比較のため、全てのPromiseオブジェクトが成功して完了した場合の出力結果も示しておこう。

失敗した場合
>node --harmony promisetest.js
reject: promise0

全て成功した場合
>node --harmony promisetest.js
resolve: promise0,promise1,promise2


Promise.allメソッドが待機する全てのPromiseオブジェクトの中でrejectされるものが出た場合

 前回は述べなかったが、この結果から分かる通り、Promise.allメソッドが返すPromiseオブジェクトは、それが待機するPromiseオブジェクトのいずれかが失敗して完了した場合には、その時点で完了する(そのため、失敗時には「promise0」のみが表示されている。これは成功時の「promise0,promise1,promise2」とは異なる結果だ)。

 では、本稿の最後に「thenable」(then可能な)オブジェクトについて見てみよう。

Copyright© Digital Advantage Corp. All Rights Reserved.

ページトップに戻る