# (穎旻試教版本)第三堂 - 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("加入購物車時發生錯誤,請稍後再試。");
}
};
```