# (穎旻試教版本)第三堂 - axios 搭配 Async/Await 再進化 # 課程大綱 1. Promise 與 Async/Await 比較 - 1 個觀念 - 20min 2. 錯誤與例外處理 - 1 個觀念 - 20min 3. axios 搭配 Async/Await 與錯誤管理整合 - 1 個觀念 - 20min # 1. Promise 與 Async/Await 比較 Promise: ```jsx function fetchData() { return new Promise(function(resolve) { setTimeout(() => { resolve("資料已經獲取"); }, 2000); }); } function getDataWithThen() { console.log("開始獲取資料..."); fetchData().then(function (data) { console.log(data); }); } getDataWithThen(); ``` Async/Await: ```jsx function fetchData() { return new Promise(function(resolve) { setTimeout(() => { resolve("資料已經獲取"); }, 2000); }); } // 使用 Async/Await 的作法 async function getData() { console.log("開始獲取資料..."); const data = await fetchData(); console.log(data); } getData(); ``` **使用 async await:提升可讀性、減少複雜性** async/await 是 JavaScript 中用於處理非同步的一種語法糖,讓程式碼更好理解 - **`async`** 關鍵字用於定義一非同步函式,這個函式將回傳一個 Promise - 在 **`async`** 函式內部,可以使用 **`await`** 關鍵字來等待一個 Promise 被解析(resolved)。 - async 函式內部可以使用 [`await`](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/await) ,他可以讓程式碼看起來像同步的,它會暫停此 async 函式的執行,並且等待解析,解析完之後會回傳解析值,並繼續此 async 函式的執行。 ## axios 寫法如下 > [請先申請 api 再練習以下程式碼](https://livejs-api.hexschool.io/) 使用 axios 套件處理非同步操作 - GET: ```jsx const api_path = "自訂路徑"; // Promise 結構的寫法 const getProductList = () => { axios.get(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/products`) .then(response => { console.log(response.data.products); }) }; getProductList(); // async / await 寫法 const getProductList = async () => { const response = await axios.get(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/products`); console.log(response.data.products); }; getProductList(); ``` 使用 axios 套件處理非同步操作 - POST: ```jsx const api_path = "自訂路徑"; // Promise 結構的寫法 function addCartItem(id){ axios.post(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/carts`,{ data: { productId: id, quantity: 1 } }). then(function (response) { alert("加入購物車成功"); }) } addCartItem('YO5KnEkeFBIEVrGDA0Id') // async / await 寫法 const addCartItem = async (id) => { const response = await axios.post(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/carts`, { data: { productId: id, quantity: 1 } }); alert("加入購物車成功"); }; addCartItem('hLk58hbZpjMMZdEPbce0') ``` # 2. 錯誤與例外處理 錯誤與[常見錯誤種類](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#error_types) ```jsx console.log(a); // ReferenceError: a is not defined ``` 自訂錯誤:[JS error 介紹](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Error) ```jsx const a = new Error("姓名欄位沒有填寫") // 建立一個 Error 物件,並指定 message a.name = "驗證失敗"; // 自訂錯誤類型的名稱 console.log(a); // 驗證失敗: 姓名欄位沒有填寫 console.log(a.name); // '驗證失敗' console.log(a.message); // '姓名欄位沒有填寫' ``` **為什麼需要學例外處理呢?** 為了在這些錯誤情況發生時,能夠加以控制或管理,稱之為例外處理,這邊我們要來介紹到 1. try...catch 語法與範例 ```jsx try { ... } catch (error) { ... } ``` ```jsx try { console.log(a); // 這邊出錯,但不會導致網頁死掉 } catch (error) { // catch 將錯誤捕捉起來,並產生一個包含詳細錯誤資訊的物件,將物件作為參數 error 使用 console.log(error) } console.log('錯誤') // 這行會被執行! ``` ```jsx // 自訂錯誤也可以用 try catch 捕捉 const a = new Error("姓名欄位沒有填寫") a.name = "驗證失敗" try{ throw a; } catch(error){ console.log(error) } ``` 2. Promise 的 catch() 語法與範例 ```jsx axios.then(function() { ... }).catch(function(error) { console.log(error) }) ``` ```jsx const getProductList = () => { axios.get(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/products`) .then(function(response) { console.log(response.data.products); }) .catch(function(error) { console.log(error) }) }; ``` ```jsx // promise 自訂錯誤使用 catch 捕捉 function customPromise() { return new Promise((resolve, reject) => { setTimeout(() => { const randomNumber = Math.floor(Math.random() * 100) + 1; if (randomNumber % 2 === 0) { resolve(randomNumber); } else { reject(new Error(`奇數: ${randomNumber}`)); } }, 1000); }); } // 使用範例 function count(){ customPromise() .then(result => console.log(`成功: ${result}`)) .catch(error => console.error(`失敗: ${error.message}`)); } count(); ``` - [axios 自訂錯誤物件](https://github.com/axios/axios/blob/main/lib/core/AxiosError.js) # 3. axios 搭配 Async/Await 與錯誤管理整合 ```jsx // GET const api_path = "自訂路徑"; const getProductList = async () => { try { const response = await axios.get(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/products`); console.log(response) } catch (error) { console.error("取得產品列表失敗", error.response.data); alert("取得產品列表時發生錯誤,請稍後再試。"); } }; // POST const addCartItem = async (id) => { try { const response = await axios.post(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/carts`, { data: { productId: id, quantity: 1 } }); console.log(response) alert("加入購物車成功"); } catch (error) { console.error("加入購物車失敗", error.response.data); alert("加入購物車時發生錯誤,請稍後再試。"); } }; ```