--- 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); }); ```