ECMA Script6(JavaScript)のPromiseオブジェクトの使い方

求人

ECMA Script6(JavaScript)のPromiseオブジェクトの使い方についてです。

ECMA Script6(JavaScript)のPromiseオブジェクトの使い方

Promiseメソッドは非同期処理を、同期処理のように扱えるオブジェクトです。

Promiseオブジェクトの概念は一番下の参考サイトを見ると非常にわかりやすいです。

Promiseオブジェクトはまずnewして使います。

promiseのthenメソッド

Promiseオブジェクトにはthenメソッドがあります。

thenメソッドには引数が2つあり、非同期処理が成功した場合は、第一引数のonFulfilled関数を実行します。

非同期処理が失敗した場合は、第二引数のonRejected関数を実行します。

以下、記述例です。

結果は以下のようになります。

Promiseオブジェクトがresolve(成功)しているのでonFulfilled関数が呼ばれています。

逆に、Promiseオブジェクトがreject(失敗)している場合の結果を見てみます。

結果は以下のようになります。

但し、thenメソッドに必ず失敗時の処理を記述しないといけないわけではありません。

通常は成功時だけの第一引数だけを記述したりします。以下はthenメソッドの第二引数を省略した例です。

省略しても結果は以下のようになります。

promiseのcatchメソッド

catchメソッドの引数は一つで、onRejected関数を指定します。その為、PromiseオブジェクトのthenメソッドではonRejected関数が省略できるというわけです。

catchメソッドが実行される例です。

結果は以下のようになり、thenメソッドが呼ばれていないのが確認できます。

thenメソッドのメソッドチェイン

thenメソッドはpromiseオブジェクトを返すのでメソッドチェインすることができます。

以下、記述例です。

最初のthenメソッドでresolve(val)ではなく、valをそのまま返しているので、この値が次のthenメソッドに渡されます。

結果は以下のようになります。

最初のthenメソッドでなにもしない場合は面白い動きをします。

次のthenメソッドの引数はundefinedになってしまいます。結果はtrueです。

要するに、thenメソッド内ではresolve,rejectをしてはいけなく、returnさえすれば次のthenメソッドにデータ結果が渡される、ということです。

以下、よく書く記述例です。

結果は以下のようになります。

then内でresolveするとエラーとなる

then内で、resolve(data);というような記述方法で詰まったことがあります。

以下、その例です。

このコードはthenの中に入り、resolveしていますが、そんな定義はないよ、と怒られてcatch句に入ってしまいます。

結果は以下のようになります。

Promise.all()メソッド

Promiseオブジェクトにはstaticメソッドがいくつか用意されています。

all()メソッドはstaticとなりますので、newせずにそのまま使用できます。

allメソッドの説明はすごく難しいですが、引数にPromiseオブジェクトを要素とした配列を持ちます。allの引数は配列である、という事を忘れがちになりますが、必ず配列でなければいけませんので注意が必要です。

Promiseの要素を持つ配列と言ったらよいでしょうか。それぞれのPromiseオブジェクトは非同期に実行されますが、実行結果の順序は配列の順序どおりであることが保証されています。

配列の各要素であるPromiseオブジェクトが全てresolveまたはrejectを返したら、Promise.all.thenメソッドが実行される、という仕組みです。

以下、例です。

結果は以下のようにcatchメソッドは呼ばれず、thenメソッドが呼ばれ、また引数は配列としてcallback関数に渡ります。

ということは片方のPromiseオブジェクトがrejectを返した場合はどういう動きをするかが気になります。

以下、実行例です。

結果は以下のようにcatchメソッドが実行されます。

allの配列のPromiseオブジェクトのいずれかがrejectを返す場合はthenメソッドは実行されずcatchメソッドが実行されるようです。また、引数はrejectした値のみが渡るようです。

Promise.allの特徴として、配列の要素にPromiseオブジェクトを格納すると、それぞれのPromiseオブジェクトは非同期に実行されます。

但し、戻り値は、配列の要素順になることが保証されていますので、非常に便利です。

以下、例です。

結果は以下のようになります。

Promise.allで配列要素が1つの場合はPromise.allを使用しない

Promise.allは複数プロミスを同時に実行できるのがメリットです。なので配列要素が1つの場合はPromise.allをわざわざ使用する必要はありません。

プロミスを変数に格納してthenすれば良いです。

Promise.raceメソッド

Promise.raceメソッドはPromise.allと非常によく似ていますが、いずれかのPromiseオブジェクトがresolveを返せばthenが呼ばれます。逆にrejectを返せばcatchが呼ばれます。

Promise.allメソッドとの違いはcallback関数に渡る戻り値に違いがあります。

以下、実行例です。

結果は以下のようにpromise1の値しか返ってきません。但し、promise2もpromise3も実行はされるようです。

Promise.resolveメソッド

Promise.resolveメソッドは完了するpromiseオブジェクトを返します。

以下、例です。

結果はthenメソッドが呼ばれます。

書き換えると以下のようにも記述できます。

結果は同じです。

参考サイト

JavaScript Promiseの本

UnhandledPromiseRejectionWarning: Unhandled promise rejection
このエラーがでる場合が時々あります。

詳細を知りたい場合、以下を記述すると詳細なエラーを出力してくれるようになります。

Promise.rejectメソッド

このメソッドはthenメソッド内で使用するとcatchに遷移します。

以下、例です。

結果は以下のようにcatch内に遷移します。

色々英語のサイトを見ていると、どうもPromise.reject()というのは以下のショートカットのようなものらしいです。

For async tests and hooks, ensure “done()” is called; if returning a Promise, ensure it resolves.

…プロミスオブジェクトがresolveまたはrejectしていないままの状態の場合にこのエラーが発生します

chainメソッド

Promise.prototype.chainメソッドが存在します。

非推奨のメソッドですが、thenメソッドのエイリアスのようです。

https://stackoverflow.com/questions/34713965/the-feature-of-method-promise-prototype-chain-in-chrome

thenメソッド内でthrowする

thenメソッド内でthrowすると、catch句に遷移します。

結果はcatch句でエラー内容が出力されます。

配列のforEachメソッド内でPromiseは使用しない

forEach内でPromise.reject();などとすると、forEachのcallback関数に戻るため、「Unhandle~~」とエラーがでます。

配列をループしたい場合はfor-ofを使用すれば、その中でrejectしても意図した動作となります。

Promiseの上手な使い方

Promiseを上手く使うには、thenに関数を渡し、それをthenで繋いでいく、といった方法が良いように思います。以下のような書き方がきれいだと思います。

ちなみにbind(this)のあとに、カンマ区切りで引数を渡すことができます。

関西で140-170/80~120万から受け付けております^^
得意技はJS(ES6),Java,AWSの大体のリソースです
Python3.6,Djangoを勉強中です,Javaは少し飽きてしまってます–;
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^

スポンサーリンク
  • このエントリーをはてなブックマークに追加
スポンサーリンク

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA