iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 29
2
Modern Web

JavaScript基本功修煉系列 第 29

JavaScript基本功修練:Day29 - axios基本語法與練習(GET、POST請求)

除了fetch外,也有不少人用axios套件來處理AJAX,非常方便易用,Vue作者更建議使用axios作為HTTP請求工具。事實上,Axios是很輕量的套件,只有約13kb,比起引用笨重的jQuery來處理AJAX,axios是更可取的選擇。

承接昨天講解fetch的文章,今天會集中整理以下有關axios的知識:

  • axios的基本語法(GET、POST)
  • axios的config寫法
  • axios的.create方法

要引入axios,可以使用npm下載,也可以直接載入CDN。

axios基本語法

axios的最基本語法:

axios(url[,config])

axios回傳的物件是Promise(fulfilled狀態),所以我們可以用.then.catch去處理成功和失敗結果。

const x = axios('https://randomuser.me/api/')
x.then((response) => console.log(x)) //Promise {<fulfilled>: {…}}

axios默認是GET請求。所以最簡單的寫法可以是這樣:

axios('https://randomuser.me/api/')
    .then( (response) => console.log(response))
    .catch( (error) => console.log(error));

但實作上比較少見這樣簡寫,通常都是axios.get(...)或者axios.post(...)這種寫法比較多,接下來看看axio本身有提供的方法。

axio請求方法

我們可以直接用axio內建好的請求方法,例如是.get.post:

//GET請求
axios.get('https://randomuser.me/api/')
    .then( (response) => console.log(response))
    .catch( (error) => console.log(error))

//POST請求
axios.post('https://hexschool-tutorial.herokuapp.com/api/signup',{
    email: 'javascriptBasics@gmail.com',
    password: '1234'
})
    .then( (response) => console.log(response))
    .catch( (error) => console.log(error))

這裏的GET要求使用了這個API,而POST要求使用了六角學院AJAX練習用的API,模擬註冊一個新帳號。

當然還有其他不同的方法可以直接使用:例如.delete.put等等,詳細可看axios在github的readme,這裏不詳細寫了。

GET請求的参數設定:
當我們需要加入参數到URL時,我們可以直接寫在URL裏,也可以拆開放在params裏面。

例如在random user的API裏,我想指定該User是女性及美國藉,那麼我就要在URL加入...api/?gender=female&nat=us

axios.get('https://randomuser.me/api/?gender=female&nat=us')
.then((response) => console.log(response)) //得出來的是類似Response的物件,裏面的data才是我們想抓的資料
.catch((error) => console.log(error))

另一個做法就是拆出來放在params裏面,這個做法與上面所做的事是一樣

axios.get('https://randomuser.me/api/',{
    //URL参數放在params屬性裏面
    params: {
        gender: 'female',
        nat: 'us'
    }
})
.then((response) => console.log(response))
.catch((error) => console.log(error))

題外話,這裏也可以用asycn/await去寫:

async function getUser(){
    try{
        const response = await axios.get('https://randomuser.me/api/?gender=female&nat=us');
        console.log(response);
    }catch(error){
        console.log(error)
    }
}

同時發出多個請求

function getUserFemale(){
    return axios.get('https://randomuser.me/api/?gender=female&nat=us')
};

function getUserMale(){
    return axios.get('https://randomuser.me/api/?gender=male&nat=us')
};

Promise.all([getUserFemale(),getUserMale()])
    .then( (response) => {
        const femaleUser = response[0];
        const maleUser = response[1];
        console.log(femaleUser);
        console.log(maleUser);
    })

axio(config物件)寫法

我們可以把所有東西(methodurldata...)放在一個物件裏,這個物件我們稱為config。例如以下寫法:

//GET請求
axios({
    method: 'get',
    url: 'https://randomuser.me/api/?gender=female&nat=us'
})
.then((response) => console.log(response))
.catch((error) => console.log(error))


//POST請求
axios({
    method: 'post',
    url: 'https://hexschool-tutorial.herokuapp.com/api/signup',
    //API要求的資料
    data: {
        email: 'alysa@gmail.com',
        password: '11223344'
    }
})
.then( (response) => console.log(response))

以上的POST例子中,我們把要傳送的資料(email,password)放在data裏面。注意,data不等於params,兩者是不同的:

  • data:傳送給伺服器的資料
  • params:在URL裏要加上的参數

結果:

config物件裏,只有url是必需的,其他都是可選。所以在一個config物件裏,可以包有很多屬性,例如以下的屬性:

axios({
method: 'post',
url: 'https://yourAPI/',
data: {
    name: 'Mary',
    age: 18
},
params: {
    ID: 123456
},
// 添加在url前面,除非url是絕對路徑
baseURL: 'https://some-domain.com/api/'
}),

...})

這裏不詳細寫所有屬性,詳細可查看axio的readme。

另外,axios預設是傳送JSON格式,如果需要application/x-www-form-urlencoded這種傳統的表單格式,就需要用qs library去處理,官方的readme也有提及這一點。

.create來預設axios裏的config物件

axios有一個很方便的方法讓我們預設config,例子如下:

//在一個axios實體物件裏,設定預設的config物件
const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});
  • baseURL:它會被添加在url前面,例如我設定baseURLhttps://some-domain.com/api,之後我傳入的URL是/productList,最終的傳送去伺服器的URL就會是https://some-domain.com/api/productList
  • headers:發出請求的表頭,裏面放AuthorizationContent-Type等等的東西。
  • timeout:如果發出請求時間出於timeout所設定的時間,請求就會被中斷。

利用.create方法,我們就少寫一些重複的東西。例如不用每次都重寫整個api網址,因為api網址前面的部分都是一樣的,也不用每次都寫一次headers。接下來會重用昨天六角學院的API例子,示範沒有使用.create方法,以及有使用.create方法的分別。

重用昨天六角學院的API例子,新增一個商品的API:

不用.create,只用一般axios的寫法

const uuid = xxxxxx;
const token = xxxxxx;


//以下是六角學院提供的商品資料,我要把這商品新增到後台
let data = {
    "title": "Abysswalker",
    "category": "T-Shirts",
    "content": "Its wearer, like Artorias himself, can traverse the Abyss.",
    "description": "This official Dark Souls shirt was designed by Nina Matsumoto and printed on soft 100% cotton shirts by Forward. Each one comes with a bonus sticker.",
    "imageUrl":['https://images.unsplash.com/photo-1529374255404-311a2a4f1fd9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1349&q=80'],
    "enabled": true,
    "origin_price": 680,
    "price": 580,
    "unit": "Item"
}

//請求表頭
let headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
    "Authorization": `Bearer ${token}`,
};


//新增商品到後台
axios({
    method: 'post',
    url: `https://course-ec-api.hexschool.io/api/${uuid}/admin/ec/product`,
    data: data,
    headers: headers
})
    .then( (response) => console.log(response))
    .catch( (error) => console.log(error))

結果:

如果之後我要查看所有商品,我又要多寫一次header和整個URL:

//查看所有在後台的商品
axios({
    method: 'get',
    //又要多寫一次整個URL
    url: `https://course-ec-api.hexschool.io/api/${uuid}/admin/ec/products`,
    //又要多寫一次headers
    headers: headers
})
    .then( (response) => console.log(response))
    .catch( (error) => console.log(error))

.create方法

.create的方法,就可以不用重複寫整個URL,也不用重複寫headers,程式碼會更簡短易讀。

首先用.create方法預設好config物件:

const uuid = xxxxxx;
const token = xxxxxx;

//新增一個變數叫HexSchool api,它是一個axios實體物件。
//我們在裏面設定config物件,讓我們之後可以重用
const apiHexSchool = axios.create({
    baseURL: `https://course-ec-api.hexschool.io/api/${uuid}`,
    headers: {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Authorization": `Bearer ${token}`,
    }
})

之後,新增商品到後台時,直接拿apiHexSchool這個axios物件來用,並在此物件使用POST方法:

let data = {
    "title": "Abysswalker",
    "category": "T-Shirts",
    "content": "Its wearer, like Artorias himself, can traverse the Abyss.",
    "description": "This official Dark Souls shirt was designed by Nina Matsumoto and printed on soft 100% cotton shirts by Forward. Each one comes with a bonus sticker.",
    "imageUrl":['https://images.unsplash.com/photo-1529374255404-311a2a4f1fd9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1349&q=80'],
    "enabled": true,
    "origin_price": 680,
    "price": 580,
    "unit": "Item"
}

//新增商品到後台。在.post()裏第一個参數,只需放入URL後面的部分
const addProduct_backend = data => apiHexSchool.post('/admin/ec/product',data);

addProduct_backend(data)
    .then( (response) => console.log(response))
    .catch( (error) => console.log(error));

結果:

接著,如果我要查看所有商品,我只需要這樣寫:

//查看後台所有商品
const getProductList_backend = () => apiHexSchool.get('/admin/ec/products');
getProductList_backend()
    .then( (response) => console.log(response))
    .catch( (error) => console.log(error));

結果:

(因為之前練習時也新增了一些商品,所以這裏的商品數量會是7,請無視陣列的長度。)

總括來說,每一次接API,我只需重用apiHexSchool這個axios實體物件就行了。因為這個實體物件裏已經設定好我想要的config,所以每次接API時,我不用重寫多一次config物件。

關於.create這個方法,它也能幫助管理好我們在程式碼所接的API。這裏推薦閱讀Mike老師的這篇文章,他提及實作時我們可能要接幾十個API,我們可以先把這些API作一個簡單分類,然後為每一個類別,用.create的方法建立axios實物,裏面設定好config物件。之後,當我們要接API時,就對應和引用之前建立好的axios物件。這裏就可以提升程式碼的可讀性,也便於管理所有API。

總結

axios和fetch都是常見用來處理AJAX的語法,對於習慣Vue開發的人,可能用axios會比較多。明天會開始講解有關接API時會遇上的問題,以及一些除錯或解決方法~

参考資料

使用Axios你的API都怎麼管理?
axios 基本使用 & Config
AJAX 完整解說系列:新增、更新、刪除(POST、PATCH、DELETE
由前端request 的幾種方法


上一篇
JavaScript基本功修練:Day28 - Fetch練習(GET和POST請求)
下一篇
JavaScript基本功修練:Day30 - AJAX常遇上的同源政策問題與解決方法
系列文
JavaScript基本功修煉31

尚未有邦友留言

立即登入留言