【JavaScript】非同期処理③　Promise


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/dd42492cbb8a916e8502

#目的

* 非同期処理についての理解を深める

#本題
###1.Promise

非同期処理をより簡単に、可読性が上がるように書けるようにしたもの。
→  コールバック関数で書いた場合、可読性が下がる。

####基本構文

````js
new Promise(
  // 同期処理
).then(
  // 非同期処理(resolveを待つ)
).catch(
  // 非同期処理(rejectを待つ)
).finally(
  // 　非同期処理(then, またはcatchを待つ)
)
`````

さらに例を用いて書いていくと下記の通りとなる

**resolve**を使用した場合

```js
// Promiseの引数としてコールバック関数を設定する
new Promise(function(resolve, reject){
  // resolveを使った場合thenメソッドを呼び出す
  resolve("hello")
}).then(function(data){
  console.log(data) //helloと出力される
}).catch(
  //  スキップされる
// finallyメソッドで使用するコールバック関数は引数を取らない
).finally(function(){
  　console.log("終了処理");
});
````

**reject**を使用した場合

```js
// Promiseの引数としてコールバック関数を設定する
new Promise(function(resolve, reject){
  // rejectを使った場合catchメソッドを呼び出す
  reject("bye")
}).then(
  //  スキップされる
).catch(function(data){
    console.log(data) //byeと出力される
  }
  // finallyメソッドで使用するコールバック関数は引数を取らない
).finally(function(){
  　console.log("終了処理");
});
````

####例1

基本的なPromise構文をコードで確認

```js
  // ここでpromiseを実行することで、thenが出力される
  // global endが先に実行される（thenが非同期で実行されるから）
  resolve();
  // 下記のように繋げて書いても多階層になることはない　＝　可読性が上がる
}).then(function(){
  console.log("then");
}).then(function(){
  console.log("then");
}).then(function(){
  console.log("then");
}).then(function(){
  console.log("then");
})

// ここでグローバルコンテキストが終了したことを証明
// then, catch, finallyが非同期実行されることが確認できる
console.log("global end")
`````

ここにcatchメソッドを追加

````js
new Promise(function(resolve, reject){
  console.log("promise");
  // rejectを実行
  reject();
}).then(function(){
  console.log("then");
}).then(function(){
  console.log("then");
  // catchメソッドを使用
}).catch(function(){
  // thenはスキップされる
  console.log("catch");
})

console.log("global end")
``````

rejectはnew Promiseの中でしか使えない
特定のthenの中でcatchに処理を移行したい場合にはthrowというキーワードを使用する

````js
new Promise(function(resolve, reject){
  console.log("promise");
  // resolveにしておく
  resolve();
}).then(function(){
  // このthenでなんらかのエラーが発生したと仮定する
  console.log("then");
  // このようにすることで1回目のthenは呼ばれるが次のthenは呼ばれない
  // 処理がcatchに移行し"catchと出力される"
  throw new Error();
}).then(function(){
  console.log("then");
}).catch(function(){
  console.log("catch");
})

console.log("global end")
`````

最後にfinallyを追加する

```js
new Promise(function(resolve, reject){
  console.log("promise");
  resolve();
}).then(function(){
  console.log("then");
}).then(function(){
  console.log("then");
}).catch(function(){
  console.log("catch");
}).finally(function(){
  // このfinallyは必ず呼ばれる
  console.log("finally");
})

console.log("global end")
````

####例2

それぞれ引数を渡して確認をする

```js
new Promise(function(resolve, reject){
  console.log("promise");
  // resolveの引数としてhelloとすると
  resolve("hello");
  // reject("bye");
  // 下記のdataがhelloとして扱われる
}).then(function(data){
  // then helloと出力
  console.log("then " + data);
  // ここで値を返却することで2個目のthenもhelloと出力される
  return data;
}).then(function(data){
  console.log("then " + data);
}).catch(function(data){
  // rejectが使われていた場合catchが呼ばれる
  console.log("catch " + data);
  // finallyは引数を取れない
}).finally(function(){
  console.log("finally");
})

console.log("global end")
`````

####例3

setTimeoutで値を出力する

```js
new Promise(function(resolve, reject){
  console.log("promise");
  // 1秒後にresolveを実行
  setTimeout(function(){
    resolve("hello");
  }, 1000);
  // このようにするとpromise, global endが先に呼ばれた後に1秒後resolveが呼ばれる
  // rejectも同様
}).then(function(data){
  console.log("then " + data);
  return data;
}).then(function(data){
  console.log("then " + data);
}).catch(function(data){
  console.log("catch " + data);
}).finally(function(){
  console.log("finally");
})

console.log("global end")

```



今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
* [Let'sプログラミング JavaScript入門](https://www.javadrive.jp/javascript/)