LoginSignup
9
13

More than 5 years have passed since last update.

【javascript】Promiseについて学ぶ①

Posted at

Promiseについてまとめます。

Promiseとは

非同期処理をわりかしすっきり書くことができる書き方。
わりかしと書いたのは、コールバックを駆使して書くよりもすっきり書くことができるという意味です。

Promiseの基本

Promiseを使うときの基本手順です。

1.Promiseコンストラクタに非同期に処理したいことを書いたコールバックを引数として渡し、オブジェクト化する

newしてオブジェクト化することができます。
コールバック関数には、引数にresolve、rejectを渡す必要があります。

2.成功時はresolve、失敗時はrejectを呼ぶ

非同期処理では、処理が成功したときはresolve、失敗したときはrejectを呼び出します。

3.Promiseオブジェクトをリターンする

4.成功時、失敗時に関数を実行したいのならば、then()メソッドを使う

Promiseオブジェクトに対してthen()を使用することで、成功時、失敗時に実行したい関数を登録することができます。

以下、サンプルコードを用いて詳しく説明します。

sample.js

1   function asyncFunc() {
2       return new Promise(function (resolve, reject) { // 手順1、3
3           // ここ以下に非同期に処理したい内容を書きます
4           async(function(err, data){ // 仮想の関数です。
5               if (err) {
6                   reject(err);  // 手順2 失敗したのでrejectを呼び出す
7               
8               }
9               resolve(data);  // 手順3 成功したのでresolveを呼び出す
10           });
11      });
12  }
13  
14  function onFulfilled(data) {
15    console.log(data);
16  }
17  
18  function onRejected(err) {
19    console.log(err);
20  }
21 
22  asyncFunc().then(onFulfilled, onRejected);  // 手順4
23 

L2: return new Promise(function (resolve, reject) {・・・

new Promise(callback)でPromiseオブジェクトを作ることができます。
callbackには非同期に処理したいことを書きます。
また、このcallbackでは引数にresolveとrejectを渡す必要があります。
newでオブジェクトを作り、returnすることで、asyncFunc関数を実行したとき(L22)にPromiseオブジェクトを返すようにします。

L6: reject(err);

ここでは仮想のasync関数を使用しています。
errがあった場合、処理は失敗とします。そのときに、rejectを呼び出します。

L9: resolve(data);

errがなかった場合、処理は成功とします。そのときにresolveを呼び出します。

L22: asyncFunc().then(onFulfilled, onRejected);

then関数を使用することによって、成功時、失敗時に実行する関数を登録することができます。
asyncFunc関数の戻り値はPromiseオブジェクトですので、then()はインスタンスメソッドです。
成功時にはonFulfilledが実行され、失敗時にはonRejectedが実行されます。
ここでいう、成功時、失敗時というのはそれぞれ、非同期処理中にresolve、rejectが呼ばれた時のことです。

L14~22 以下のようにも書けます

sample-then.js
1  asyncFunc().then(function (data) {
2      console.log(data);  // onFulfilled
3  }, function (err) {
4      console.log(err);  // onRejected
5  });

L14~22 catchを使って以下のようにも書けます

sample-catch.js
1  asyncFunc().then(function(data) {
2      console.log(data);
3  }).catch(function(err) {
4      console.log(err);
5  });

.catch()については、.then(undefined, onRejected)と同じ意味になります。

Promiseオブジェクトの状態

インスタンス化したPromiseのオブジェクトには3つの状態があります。

  • Fulfilled
    • 成功したとき。すなわちresolveされたとき。このときonFulfilledが呼ばれる
  • Rejected
    • 失敗したとき。すなわちrejectされたとき。このときonRejectedが呼ばれる
  • Pending
    • FulfilledでもRejectedでもないとき。初期状態等が含まれる。

非同期処理の中で成功と判断したときにresolve()を呼び出す→Fulfilledの状態になる
非同期処理の中で失敗と判断したときにreject()を呼び出す→Rejectedの状態になる
ということのようですね。

resolveされたときはthen()の第1引数に渡された関数が実行されます。
rejectされたときはthen()の第2引数に渡された関数、もしくはcatch()に渡した関数が実行されます。

thenとcatch

rejectされたときの関数の実行について、then()とcatch()だと動きが異なります。

sample-then.js
1  asyncFunc().then(function (data) {
2      console.log('onFulfilled' + data);  // onFulfilled
3  }, function (err) {
4      console.log('onRejected' + err);  // onRejected
5  });

上記のsample-then.jsの場合、asyncFunc関数でRejected状態になったときにL4が実行されます。
また、asyncFunc関数でFulfilled状態になったときは、L2が実行されます。このL2が実行されているときにエラーが起きた場合(このコードだと発生しませんが・・・)には、L4は実行されません。

sample-catch.js
1  asyncFunc().then(function(data) {
2      console.log('onFulfilled' + data);
3  }).catch(function(err) {
4      console.log('onRejected' + err);
5  });

上記のsample-catch.jsの場合、asyncFunc関数でRejected状態になったときにはsample-then.jsと同様、L4が実行されます。
また、asyncFunc関数でFulfilled状態になったときも同様に、L2が実行されています。
ですが、L2が実行中にエラーが起こった場合もL4が実行されます。この点がthenを使ったときと違う動きとなります。

上記のようなそれぞれの動きに違いを考えて、使用する必要があります。

今回はここまでとします。
次はall()についてまとめようと思います。

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