---
# System prepended metadata

title: JavaScript核心篇 -  async、await
tags: [' await', async]

---

---
title: JavaScript核心篇 -  async、await
tags: async, await
description:
---

JavaScript核心篇 -  async、await
===

### 什麼是 async 與 await

下面這段程式碼是用**Promise**、**Promise鏈接**，連續性（逐步）發送請求。

```javascript=
function promiseFn(boolean) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (boolean) {
        resolve('成功');
      } else {
        reject('失敗');
      };
    }, 500);
  });
};

promiseFn(true)
  .then((res) => {
    console.log(res);
    return promiseFn(true);
  })
  .then((res) => {
    console.log(res);
  })
```

現在要用**async**的方式，逐步發送請求。

要使用`async Function`，在**宣告Function前面要加上async**。

```javascript=
async function getData() {

};
getData();
```

:::success
asyncu意指**非同步**，在**async Function**的作用域內，可以**把Promise轉為同步執行**。
:::

```javascript=
async function getData() {
  const res1 = await promiseFn(true);
  const res2 = await promiseFn(true);
  console.log(res1, res2);
};
getData();
```

:::success
**async Function**就是透過**await**建構子，可以把**非同步執行**的promise**轉為同步執行**。
:::

ex：上面的例子可以簡化成
```javascript=
const getData = async () => {
  const res1 = await promiseFn(true);
  const res2 = await promiseFn(true);
  console.log(res1, res2);
};
getData();
```


ex：用**立即函式**的方式，變成**立即執行不用另外呼叫**的async Function。
```javascript=
(async () => {
  const res1 = await promiseFn(true);
  const res2 = await promiseFn(true);
  console.log(res1, res2);
})();
```

<br>

### 為什麼叫做Async Function

```javascript=
function promiseFn(boolean) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (boolean) {
        resolve('成功');
      } else {
        reject('失敗');
      };
    }, 500);
  });
};

async function getData() {
  return await promiseFn(true);
};
console.log(getData());
```
從`console.log(getData())`來看，==**Async Function**本身就是一個Promise==。

![](https://i.imgur.com/Z9OSLrv.png =50%x)

所以`getData()`也可以用`.then()`的方式來接收資料。

（`return await promiseFn(true)`是要把==resolve的結果傳出來==）

:::success
在**Async Function**。**return**等同**resolve**，**throw**等同**reject**。
:::
```javascript=
getData()
  .then((res) => {
    console.log(res);
  })
```
#### 如果Async Function接收失敗，怎麼辦？
可以使用**trycatch**，去try（測試）Promise函式能不能動，不行就把catch傳出來（reject()錯誤訊息）。

```javascript=
async function getData() {
  try {
    return await promiseFn(false);
  } catch (error) {
    throw(error);
  }
};

getData()
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });
```
用`throw(error)`把錯誤資訊傳出來。`getData().catch((err) => {})`才能接收到。

<br>

:::success
`await`**無法把非Promise base**的方法轉為**同步執行**。
:::

下面的例子`console.log()`印出的順序1、3、2。
- `setTimeout`不是基於`Promise`，所以`await`==無法==將`setTimeout`轉為同步執行。

    ```javascript=
    (async () => {
      console.log('1');
      await setTimeout(() => {
        console.log('2');
      }, 1000);
      console.log('3');
    })();
    ```
- 除非用`new Promise`去建立函式，把`setTimeout`包起來。

    ```javascript=
    function delayTime() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(console.log('2'));
        }, 1000)
      })
    };

    (async () => {
      console.log(1);
      await delayTime();
      console.log(3);
    })();
    ```
- 這樣就能用`await`把`setTimeout`==轉為同步執行==。

<br>

### async 與 await 的功用與實戰

**範例1**
將原本用**Promise鏈接**撰寫**連續性請求**的方式，改成==用async Function的撰寫方式取代Promise==。 
:point_right: [如何撰寫連續性請求Request](https://hackmd.io/ykQHzI04Roi3xntGScVepw#如何撰寫連續性請求Request)

- `axios.get()`前面加上`await`轉為**同步執行**，再賦予給變數res1。

- `console.log(res1.data.results[0])`印出第一筆資料。

- 用解構賦值，取得第一筆資料seed值。

- 因為取得第二筆資料必須跟第一筆**相同**，所以取第二筆資料的==API要加上seed值==， `https://randomuser.me/api/?seed=${seed}`才能**取得同一筆資料**。

- 要加上`trycatch`才能把**錯誤訊息**傳出來。 

```javascript=
(async () => {
  try {
    const res1 = await axios.get('https://randomuser.me/api/');
    console.log(res1.data.results[0]);
    const { seed } = res1.data.info;
    const res2 = await axios.get(`https://randomuser.me/api/?seed=${seed}`);
    console.log(res2.data.results[0]);
  } catch (error) {
    throw(error);
  }
})();
```

<br>

**範例2**
將原本用**Promise**撰寫**同時請求**的方式，改成==用async Function的撰寫方式取代Promise==。 

:point_right: [如何撰寫同時發出多個請求](https://hackmd.io/ykQHzI04Roi3xntGScVepw#如何撰寫同時發出多個請求)

- 要加上`trycatch`才能把**錯誤訊息**傳出來。 
```javascript=
async function getData () {
  try {
    return await Promise.allSettled([
      axios.get('https://randomuser.me/api/'),
      axios.get('https://randomuser.me/api/'),
      axios.get('https://randomuser.me/api/'),
    ]);
  } catch (error) {
    throw(error);
  }
};

getData()
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });
```

