【JavaScript】Promiseについて

今回はPromiseについての備忘録です。


## 1:「Promise」とは？
・【非同期処理を、より簡単に書けるようにしたもの】です。

・非同期処理といえばコールバック関数がありますね。
そんなコールバック関数も「チェーン」により処理を繋げることができます。
⬇︎
```javascript:main.js
//////コールバック関数の「チェーン」の例。

//⬇︎①sleep関数を定義する。
//引数にはcallbackに「コールバック関数function(val)」が渡ってくる。
//setTimeout内で「コールバック関数function(val)」が実行される。
function sleep(callback, val) {
  setTimeout(function() {
    console.log(val++);  //コンソール結果　「0, 1, 2, 3,」と1秒ずつ値が表示される。
    callback(val);
  }, 1000);
}


//⬇︎②sleep関数を実行する。
//「sleep関数の中のコールバック関数(function(val)の中で【更にsleepを呼びます。】」
//これが【複数の非同期処理を順番に実行する、非同期処理のチェーン】です。
sleep(function(val) {
  sleep(function(val) {
    sleep(function(val) {
      sleep(function(val) {
  
      }, val);
    }, val);
  }, val);
}, 0);



```
⬇︎
❌ここで問題となるのはsleepの中で更にsleepを読み込むため、「多階層が深くなりコードの可読性が下がります。」
⬇︎
❌そのため「コールバック関数というのは、非同期のチェーンを繋げるために適した記述では無い」ことが分かります。
⬇︎
⭕️この問題を解決するために【Promiseという非同期処理のチェーン】を繋げるためのオブジェクトが導入されました。
<br>




## 2: 「Promiseの書き方」
・Promise構文
⬇︎
・new Promise➡︎「Promiseをインスタンス化」してあげます。

・.thenメソッド、.catchメソッド、.finallyメソッドを使って➡︎「非同期処理に対して制御を加えてあげることになります。」
<br>
```javascript:main.js
////Promise構文
new Promise(function(resolve, reject)
 //同期処理が実行される。
).then(
 //非同期処理が実行される。
).catch(
 //非同期処理が実行される。
).finally(
 //非同期処理が実行される。
);

```

```javascript:main.js
////⬇︎上記のPromise構文を参考にした具体例。
//多階層にならないのでPromiseは非同期処理のチェーンを処理するために適した記述です。
new Promise(function (resolve) {
  resolve('hello');
}).then(function(data) {
    console.log(data); //コンソール結果➡︎コールスタックが空っぽになった後に、’hello’が出力される。
  })
  .then(function(data) {
    console.log(data); //コンソール結果は同じく’hello'で、しかも多階層にならない！Promiseは非同期処理のチェーンを処理するために適した記述方法！
  })
  .catch(function(data) (
    console.log('エラーだよ'); //catchはエラー処理。
  ).finally(function(){
    console.log('終了') //finallyで終了処理。
  });

```
⬇
■new Promiseの引数として「function(resolve, reject)」を設定します。

__・resolveが呼ばれた場合__
解決処理が実行される。
「resolve」が呼ばれた場合には【.thenメソッドの中のコールバック関数function(data)が実行されることになり、引数dataにはresolveで渡した実引数'hello'などが渡ってきます。」


__・rejectが呼ばれた場合__
エラー処理が実行される。
「reject」というのは【Promiseのコールバック関数で、エラーが発生した時にPromiseに通知してあげるために使用する関数】です。


__・引数function(data)__
resolve(‘hello’)や、reject('bye')で渡した実引数’hello’や'bye'が渡ってきます。 
<br>

■「then, catch, finally」の各解説。

・thenメソッド
resolveで条件に一致したら実行される。catchメソッドはスキップされて、finallyメソッドに処理が移ります。

・catchメソッド
rejectでエラー処理が実行される。.catchメソッドが完了したら、.finallyメソッドに処理が移ります。

・finallyメソッドが呼ばれた場合
thenメソッド、catchメソッドの後に呼ばれるfinallyメソッドは終了処理を記述していきます。
.finallyメソッドの中で使用するコールバック関数functionは、【(data)引数を取ることができません。








## 3: 「Promiseの書き方:2」
Promiseのおかげで非同期処理しやすくなったな〜と実感してきた所で、

①「throw new Error」でthenメソッドから➡︎catchのエラー処理を強制実行する。

②「setTimeoutを使った非同期処理の書き方」の紹介。

などの実装をしてみます。（少し見えにくいかもしれませんがご容赦ください…。）

```javascript:main.js
////①「throw new Error」でthenメソッドから➡︎catchのエラー処理を強制実行する。
new Promise(function (resolve, reject) {
  console.log('promise 開始');
  resolve('hello'); //⬅︎resolveでthenを実行する。
  //reject('bye');
})
  .then(function (data) {
    console.log('then①:' + data); //⬅︎コンソール結果：then①:hello
    throw new Error(); //⬅ここでthrow new Errorを使うと「catchの処理が強制実行します。」
    return data; //⬅return dataを設定すると「次の処理にdata(resolveやrejectの引数hello)を渡せる。
    //throw new Error();をコメントアウトするとhelloを渡せる。
  })
  .then(function (data) { 
   //このthenメソッドは無視されcatchに処理が移る。
    console.log('then②:' + data);
    return data;
  })
  .catch(function (data) {
     console.log('エラーcatch:' + data); //⬅︎コンソール結果：エラーcatch
  })
  .finally(function () {
    console.log('finally'); //⬅︎最後にfinallyで終了。
  });

console.log('global end 終了'); //同期的に処理されるので「コンソールのpromise開始のあとに出ます。」

```






<br>

```javascript:main.js
////②「setTimeoutを使った非同期処理の書き方」の紹介。
new Promise(function (resolve, reject) {
  console.log('promise 開始');
  //⬇︎setTimeoutを実行。1秒後にresolveでthenメソッドを処理していく。
  setTimeout(function () {
    resolve('hello');
  }, 1000);
  //reject('bye');
})
  .then(function (data) {
    console.log('then①:' + data); //コンソール結果: then①:hello
    return data;
  })
  .then(function (data) {
    console.log('then②:' + data); //コンソール結果: then②:hello
    return data;
  })
  .catch(function (data) {
    //このcatchメソッドは今回はもちろん実行されない。
    // console.log('catch:' + data);
  })
  .finally(function () {
    console.log('finally'); //⬅︎最後にfinallyで終了。
  });

console.log('global end 終了'); //同期的に処理されるので「コンソールのpromise開始のあとに出ます。」


```

⭕️Promiseのおかげで「コールバック関数などの非同期処理を、見やすく書けるようになります。」




<br>

 ## 4:「Promise」の備忘録でした

こうしてインプットとアウトプットを繰り返していると、記憶に定着して1歩ずつ進んでいるなと感じます。