上篇提到 Axios 是 Clinet 與 Server 溝通的方法之一。
這篇會提到 Axios 是什麼
、如何安裝
、使用起手式
、以及 Axios 特色方法 攔截器
、封裝等。
話不多說,跟著我的腳步,我們一起走吧!!
Axios is a promise-based HTTP Client for node.js and the browser. It is isomorphic (= it can run in the browser and nodejs with the same codebase). On the server-side it uses the native node.js http module, while on the client (browser) it uses XMLHttpRequests. - 取自 Axios 官網
翻譯一下大概就是:
Axios 是由 Promise 的 Http 庫組成的套件。
當使用在客戶端(Client)時,是採取 XMLHttpRequests 的原生庫來進行封裝。
當使用在伺服器端(Server)時,則是採取 Http Module 來進行封裝。
我想上面的部分有點繞口,所以以下這幾點則是我的翻譯以及一些使用前須知,建議先閱讀之後在進行使用。
XMLHttpRequest
、 HttpModule
來進行實作,這些方式都是一些原生的類別,所以您可以理解成在兼容性不會有其他阿咂的問題。包裝請求
(建立 Request)-> 伺服器回傳相應資訊
(回傳 Response); 所以在建立 Request 的過程中需要進行相應的設定
來告知 Axios 該怎麼組成請求,回傳 Promise
,在使用上可以透過 then/catch/finally 來獲取請求完成狀態,相較 XMLHttpRequest 在使用上來的更加精簡,當然因為是 Promise 物件所以可以透過 async/await 進行同步等待。在專案中,使用方式有兩種:
npm install axios
yarn add axios
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">
在使用之前我們先來了解一下 Request 的 config,下面會挑選幾個常用的設定進行介紹。
axios({
//- `url`: 相對/絕對路徑,當 baseURL 並未進行設定時,需為絕對路徑。
url: "/call/me",
//- `method`: 請求方法最常聯想到的是 RESTful API : GET POST PUT PUTCH DELETE
method: "get",
//- `baseURL`: 設定 API 所屬網域
baseURL: 'https://thisCanGiveMeDataWebAPIURL.com',
//- `headers`: Request Header 設定最常設定內容有 APIToken
headers: {'X-Requested-With': 'XMLHttpRequest'},
//- `params`: 會隨請求一起發送的 URL 參數,當 Method 為 GET 時會當作是 payload 一同送出。
params: {
ID: 12345
},
//- `data`: 為 body 實體送出,僅能使用於'PUT'、'POST'、'DELETE 和 'PATCH'
data: {
firstName: 'Fred'
},
//- `timeout`: 當設定毫秒數到時會自動取需 API 溝通。
timeout: 1000,
//- `withCredentials`: 表示是否跨站訪問控制請求
withCredentials: false,
//- `auth`: 此參數為了是與後端透過 Authorization header 進行溝通時需要進行設定,如果您的需求是 Bearer tokens 時則需直接在 header 裡面建立 {Authorization: `Bearer ${token}`}
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
//- `responseType`: response 回覆格式
responseType: 'json',
//- `responseEncoding`: response 回覆編碼
responseEncoding: 'utf8',
//- `cancelToken`: 用於取消請求
cancelToken: new CancelToken(function (cancel) {}),
...
})
在發送請求後,當然會有一個回傳的資料摟~而這邊的回傳資料。
下列幾個是一定要知道的 Reaponse 類別。
{
// `data`: Server 回應 Data 實體
data: {},
// `status`: Server 回應此請求 Http Status Code
status: 200,
// `statusText`: Server 回應此請求 Http Status Code message
statusText: 'OK',
// `headers`: Server 回應此請求的 header
headers: {},
...
}
在了解上面的基本設定之後我們來開始使用他吧!但只是單純空講我相信還是會很不清楚包含我自己,所以我們這邊的例子就依照 台中市政府資料公開平台
的臺中市領有溫泉標章之溫泉
來進行實作吧!!
E.G. GET
axios({
method: 'get',
baseURL: 'https://datacenter.taichung.gov.tw/Swagger',
url:'/OpenData/678b53a2-6de4-4052-90b4-0847eb1d7a5b',
params: {}
})
.then(res=>{
console.log(res)
})
.catch(err=>{
console.log(err)
})
可以看到這邊將 res 直接進行 console.log 出來的結果會是
是不是更上面所說的 Reaponse
物件一樣呢,所以聰明的你應該已經想到該怎麼透過物件來取的資料了對吧!
沒錯就是透過 res.data
來獲取資料內容!!
附上進行資料處理的過程
axios({
method: 'get',
baseURL: 'https://datacenter.taichung.gov.tw/Swagger',
url:'/OpenData/678b53a2-6de4-4052-90b4-0847eb1d7a5b',
params: {}
})
.then(res=>{
const data = res.data.reduce((obj,datum) => {
if(!(datum.溫泉地區 in obj)) obj[datum.溫泉地區] = []
obj[datum.溫泉地區].push({name:datum.經營名稱, place: datum.溫泉地區})
return obj
},{})
let str = ''
Object.entries(data).forEach(([key,value])=> str+=`<h3>${key}</h3><ul>${value.map(node=>`<li>${node.name}</li>`).join('')}</ul>`)
document.getElementById('tag').innerHTML = Object.keys(data)
document.getElementById('wrap').innerHTML = str
})
.catch(err=>{
console.log(err)
})
這樣就可以條列式的看見領有溫泉標章之溫泉的廠商摟 Demo!
E.G. POST
axios({
url: 'blog/new',
method: "POST",
baseURL: 'https://yourDomin.com/',
data:{
account: 'test111',
body:'<h1>測試</h1>'
}
})
.then( (response) => console.log(response))
.catch( (error) => console.log(error))
我相信工程師都是偷懶的,人因偷懶而進步,於是我們來學習怎麼偷懶吧(誤)!
相信大家在使用 Axios 時都會感覺到厭煩,因為在每次的發送之前都需要進行一大堆的設定 config,像是 baseURL 反覆設定。
axios({
method: 'get',
baseURL: 'https://datacenter.taichung.gov.tw/Swagger',
url:'/OpenData/678b53a2-6de4-4052-90b4-0847eb1d7a5b',
params: {}
})
又或者當需要 token 時總是會反覆寫相同的判斷。
const config = {
method: 'get',
baseURL: 'https://datacenter.taichung.gov.tw/Swagger',
url:'/OpenData/678b53a2-6de4-4052-90b4-0847eb1d7a5b',
params: {}
}
if(needToken) config.header.apiToken = token
axios(config)
於是乎我們來學會封裝吧。
先來定義我們想要怎麼呼叫來降低重複 codeing。
我希望在使用的時候建立 xhr.js,透過 import 的方式將封裝後的 axios 引用至需要 js 檔案之中,並且呼叫 xhr(config) 來建立 axios 請求。
//- 預期使用方式
//- needToken 判斷是否需要 token
xhr({
needToken,
url,
method,
params,
data,
})
//- xhr.js
const xhr = ({url,data,params,method,needToken}) => {
//- 建立相同設置,這裡可以做很多很多事情,例子中是透過 needToken 來控制是否需要 token
const _axios = axios.create({
baseURL: 'https://datacenter.taichung.gov.tw/Swagger',
headers: { 'Content-Type': 'application/json' },
timeout: 20000
});
return new Promise((resolve,reject)=>{
const config = {url,data,params,method}
if(needToken) config.headers.token = token
_axios(config)
.then((res)=> resolve(res.data))
.catch((err)=>reject(err))
})
}
export default xhr
//- 外部引用方式
xhr({
url:'/OpenData/678b53a2-6de4-4052-90b4-0847eb1d7a5b',
method: 'get',
needToken: false,
})
.then(res=>res)
.catch(err=>err)
多了一層的 xhr 來進行封裝 axios 可以針對特殊處理像是 1. token 判斷 2. 針對回傳進行特定處理 3. token 失效進行什麼判斷... 等,有很多的應用可以在這一層進行處理。
其實針對上方寫法, Axios 其實有提供 Interceptor(攔截器)
,來擷取發送 request 之前、獲取 response 之後,可以進行相應的設定,通常用於所有 request / response,相同的資料處理,詳情可以看下面這張圖片。
所以我們可以改寫上方的 xhr.js ,就更加精簡摟。
設定 axios interceptor
const xhr = () => {
const _axios = axios.create({
baseURL: 'https://datacenter.taichung.gov.tw/Swagger',
headers: { 'Content-Type': 'application/json' },
timeout: 20000
});
// 攔截 Request
_axios.interceptors.request.use((req)=>{
//- 這裡要特別註記
if(needToken) req.headers.token = 'rereqwrwevmlpodsjvopsdkv'
//- 針對 config 進行配置
return req
},err=> {
//- 當請求發送失敗時,此狀況在於無法發送的狀態
return Promise.reject(err);
})
// 攔截 response
_axios.interceptors.response.use((res)=>{
//- 針對回傳進行相應處理,可能是擷取部分資訊。
return res.data
},err => {
//- 當伺服器端回應失敗,
return Promise.reject(err)
})
returm _axios
}
export default xhr
//- 外部引用方式
xhr({
url:'/OpenData/678b53a2-6de4-4052-90b4-0847eb1d7a5b',
method: 'get',
needToken: false,
})
.then(res=>res)
.catch(err=>err)
如何是不是變的簡單明瞭,好維護了呢,大致上就是這些摟!!
謝謝各位觀看!!
Axios GitHub
[Axios] (https://axios-http.com/docs/intro)