# 第三堂:axios 搭配 Async/Await 再進化 ## 開課提醒 1. 記得錄影 ## 課程大綱 1. 基本 Promise 與 Async/Await 比較 * 1 個觀念 - 20min 2. 錯誤管理 * 1 個觀念 - 20min 3. axios 搭配 Async/Await 錯誤管理整合 * 1 個觀念 - 20min # 1. 基本 Promise 與 Async/Await 比較 ```jsx // 一個模擬的非同步函式 function fetchData() { return new Promise((resolve) => { setTimeout(() => { resolve("資料已經獲取"); }, 2000); }); } // 傳統寫法 // 使用 Promise 的 .then() 方法來處理非同步操作 function getDataWithThen() { console.log("開始獲取資料..."); fetchData().then((data) => { console.log(data); // 會在 2 秒後輸出 "資料已經獲取" }); } getDataWithThen(); // 使用 Async/Await 的作法 async function getData() { console.log("開始獲取資料..."); const data = await fetchData(); console.log(data); // 會在 2 秒後輸出 "資料已經獲取" } 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 寫法如下 ```jsx // 傳統 axios 寫法 const api_path = "自訂路徑"; // GET const getProductList = () => { axios.get(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/products`) .then(response => { console.log(response.data.products); }) }; // POST 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("加入購物車成功"); }) } // async / await 寫法 // GET const getProductList = async () => { const response = await axios.get(`https://livejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/products`); }; // POST 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("加入購物車成功"); }; ``` # 2. 錯誤處理 - [JS error 介紹](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Error)、[常見錯誤種類](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#error_types) - [axios 自訂錯誤物件](https://github.com/axios/axios/blob/main/lib/core/AxiosError.js) - try catch 可處理 - 程式錯誤 - 自訂錯誤 (例:axios 的 promise catch 自訂錯誤、開發者自訂錯誤) ```jsx // 自訂錯誤 const a = new Error("姓名欄位沒有填寫") a.name= "驗證失敗" try{ throw a; }catch(error){ console.log(error) } // SyntaxError 錯誤 let x = (10 + 5; // ReferenceError 引用了一個不存在的變數 console.log(b); ``` ### promise 自訂錯誤 ```javascript 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 自訂錯誤 ```javascript! const api_path = "自訂網址"; // GET const getProductList = () => { axios.get(`https://vejs-api.hexschool.io/api/livejs/v1/customer/${api_path}/products`) .then(response => { console.log(response.data.products); }) .catch(error=>{ console.log(error.name) }) }; ``` # 3. axios 搭配 Async/Await 錯誤管理整合 ```jsx // async / await 寫法 // 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); } }; getProductList(); // 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); alert("加入購物車時發生錯誤,請稍後再試。"); } }; ```