javascript promise について

## 始めに
javascript学習中であり、学習様にまとめます。非同期処理の仕組みを振り返り、promise、async awatを学習していきます。

## 同期処理　非同期処置
- 同期処理
 - メインスレッドでコードが順々に実行される。
 - １つの処理が終了しないと、次の処理へ移行しない。
 - 本来処理はコールスタックに積まれていきその積まれたスタック（実行中のコードのコンテキスト）がlast in first outの原則で処理がスタックがはけていく。

- 非同期処理
 - 同期処理は処理が実行されるまで次の処理が移行しないが、非同期処理を行うことで、処理をメインスレッドから分離ができる。
 - この分離している期間を利用して、次の同期的処理を実行できると言うことだ。
 - 分離された処理が全てのコールスタックがはけて、戻ってこれる。
 
同期
 ![スクリーンショット 2020-12-16 23.11.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574630/f1847f2e-a6af-b306-0156-528ba837e700.png)
非同期
![スクリーンショット 2020-12-16 23.11.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574630/37c8950c-7eeb-bb3e-324a-18a24534892a.png)

##  タスクキュー
- 実行待ちの非同期処理の行列
- 非同期処理の実行順はfirst in first outの原則からキューの中に入ってきた処理順に実行される

## 非同期処理の例
setTimeoutは一般的な非同期処理である
ここでのconsole.logの実行中を見ると、test()を実行した段階で、setTimeoutによって処理の分離が行われる。そしてtest2が実行。そして、次のコンテキストに移り、test3が実行。
test3が実行された段階で、キューからコールスタックに切り離された処理が戻り、task3が実行される。

```js

//非同期処理の例
const test = () => {
  setTimeout(() => {
    console.log("test1");
  }, 4000);

  console.log('test2');
};

const test2 = () => {
  console.log('test3');
}

test();
test2();

//console.logの表示順
test2->test3->test

```
## 非同期処理のチェーン
非同期処理はチェーンできるが、繋げれば繋げるほど可読性が悪くなる

```
const test = (callback, val) => {
  setTimeout(() => {
    console.log(val++);
    callback(val);
  }, 1000);
};

test((val) => {
  test( (val) => {}, val)
}, 1);

```
その為作られたのがpromise

## Promise
- 非同期処理を簡単に書ける様にした仕組み
- 非同期処理を操作できるオブジェクト。
- promiseの引数として、resoleve, rejectをとることができる。
- promiseは.thenメソッドでチェーンとして処理をつなげることができる
 - サーバーに繋ぐ .then データを取得します .then データを取得したら処理をします。と言う具合に処理を繋げることができる。
- 状態とはresolve(ok)、reject(ng)として受け取ることができる。

構文としては

```js

//Promiseはコールバックをとる。その引数にresolve、rejectをとることができる。
const test = new Promise((resolve, reject) => {
  //同期処理
}).then(() => {
  //非同期処理（resolveを待つ）
}).catch( () => {
  //非同期処理(rejectを待つ)
}).finally( () => {
  //非同期処理
})


```
then()メソッドの記述

```js

const test = new Promise((resolve, reject) => {
  //引数で受け取ったresolveを使用する。
  resolve("hello");
}).then((data) => {
//resoleve()の引数がthen()の引数となる。
  console.log(data);
});

//catchの場合

const test = new Promise((resolve, reject) => {
  reject("test");
})
  .then((data) => {
    console.log(data);
  })
  .catch((data) => {
    console.log(data)
    //次then()にdataを渡す場合
    return data;
  }).then( (data) => {
     console.log(data);
  });

console.log("globle test");
→結果：　globle test, test

//rejectはPromiseで渡すコールバックでしか使用できないので、then()なで処理の分岐をする場合はthrow new Errorで処理の分岐を行う

const test = new Promise((resolve, reject) => {
  reject("test");
})
  .then((data) => {
    console.log(data);
    throw new Error()
  })
  .catch(() => {
    console.log("error catch");
  });

console.log("globle test");
結果：globle test , error catch

```
## Promiseチェーン
promiseを使用して複数の非同期処理を実行する。

```js

const testPromise = (val) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(val++);
      resolve(val);
    }, 4000);
  });
};

//testPromiseを実行してタイミングで戻り値としてpromise関数が返却されるのでthen()が使用できる
testPromise(0)
   //ここの引数のvalはtestPromise関数の引数であるval
   //なぜvalの値が０にならにかと言うと、処理を連続して繋げているから
  .then((val) => {
    return testPromise(val);
  })
  .then((val) => {
　　　//return で必ずPromiseのインスタンスを返さないと処理が切れてしまう。
    return testPromise(val);
  });

```
## Aysnc Await
Pomiseをさらに直感的に書ける様にした仕組み

### Async
- promiseを返却する関数を宣言する。関数の前にaysncをつける

### Await 
- promiseを返却する関数の非同期処理が実行されるまで待つ。
- 処理が実行されたら次の処理に移る

実際のコード

```js

const testPromise = (val) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(val++);
      resolve(val);
    }, 4000);
  });
};

//asyncで宣言を行う
const test = async () => {
　//awaitで非同期処理が完了するまでまつ。その結果を変数に代入する
  let val = await testPromise(0);
  console.log(val);
};

test();

//処理を繋げることも可能

const test = async () => {
  let val = await testPromise(0);
  val = await testPromise(val);
  val = await testPromise(val);
  val = await testPromise(val);
  val = await testPromise(val);
};

test();

```
Promiseを使用しているのでもちろんthen()を使用できる.


```js

const testPromise = (val) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(val++);
      resolve(val);
    }, 4000);
  });
};

const test = async () => {
  let val = await testPromise(0);
  val = await testPromise(val);
  return val;
};

//test()でもpromiseの処理の後にthen()が実行される
test().then(() => {
  console.log("hello" + val);
});

```

error　catchもできる

```react

const testPromise = (val) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(val++);
      resolve(val);
    }, 4000);
  });
};

const test = async () => {
  let val = await testPromise(0);
  val = await testPromise(val);
  throw new Error();
  return val;
};

test()
  .then((val) => {
    console.log("hello" + val);
  })
  .catch((e) => {
    console.log(e);
  });

```

## try catch

promiseチェーンで処理を繋げて,exceptionがあれば.catchでエラーを出力していたが、try , catch文でも同様のことができる。

```react
import React, {useState, useEffect} from 'react'
import axios from 'axios';

const User = () => {
    const [user, setUser] = useState({});
  
    const getUser = async () => {
      try {
           const res = await axios.get('api_path');
           setUser(resd.data);
      } catch(err) {
           console.log(err);
      }
   }
   
   useEffect(() => {
       getUser();
   }, [])
}

```
## 終わりに
非同期処理を学習しました。次ぎはtry catchを追加していこうと思います。