翻譯:Da
原文地址:blog.logrocket.com/how-to-make…
對前端工程師來說,跟伺服器交流的最通用方式就是Http協議,我們比較熟悉的傳送請求的方式有Fetch API和XMLHttpRequest。下面我們會全面的介紹Axios —— 一個基於瀏覽器內建的XMLHttpRequest介面的HTTP API庫,看看是哪些優秀的功能讓它在前端開發者中越來越流行。
選擇Axios的原因
跟Fetch一樣,Axios也是基於Promise的。但是,它提供了更強大,更靈活的特性配置。以下是相對於原生Fetch API的優點。
- 可以攔截請求和響應
- 簡化錯誤處理
- XSRF防禦
- 支援上傳進度
- 支援響應超時
- 支援請求取消
- 支援舊版本瀏覽器
- 自動轉換JSON資料
安裝
你可以使用以下方法安裝
- npm:
$ npm install axios
複製程式碼
- bower:
$ bower install axios
複製程式碼
- 引入指令碼
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
複製程式碼
傳送請求
在axios中,傳送請求是非常簡單的,只需要將配置物件傳給Axios函式即可,url屬性是必填的;method預設為get。下面來看一個簡單的例子
// send a POST request
axios({
method: 'post',
url: '/login',
data: {
firstName: 'Finn',
lastName: 'Williams'
}
});
複製程式碼
用過JQuery的同學應該看著挺眼熟的,它的用法很像$.ajax。上面的程式碼實現了傳送Post請求到/login,並攜帶一個物件作為引數,Axios會自動將引數轉換為JSON格式,將其作為請求正文傳送。
方法速記
Axios同樣提供了一系列的速記方法,用來執行不同型別的請求。
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.head(url[, config])
- axios.options(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
舉例如下,以下程式碼展示了前面的例子怎麼用axios.post重寫:
axios.post('/login', {
firstName: 'Finn',
lastName: 'Williams'
});
複製程式碼
處理響應
一旦HTTP請求發起,Axios就會返回一個Promise物件(fulfilled或rejected,取決於後端服務的響應),我們可以使用then()處理返回的結果,如下:
axios.post('/login', {
firstName: 'Finn',
lastName: 'Williams'
})
.then((response) => {
console.log(response);
}, (error) => {
console.log(error);
});
複製程式碼
如果返回的promise是fulfilled的,那麼作為then()第一個引數的函式將會被執行;若promise是rejected的,作為第二個引數的函式會被執行。根據文件所述,fulfilled狀態的value包含以下內容:
{
// `data` is the response that was provided by the server
data: {},
// `status` is the HTTP status code from the server response
status: 200,
// `statusText` is the HTTP status message from the server response
statusText: 'OK',
// `headers` the headers that the server responded with
// All header names are lower cased
headers: {},
// `config` is the config that was provided to `axios` for the request
config: {},
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance the browser
request: {}
}
複製程式碼
下面我們以向一個GitHub API傳送請求為例,看看它的返回值:
axios.get('https://api.github.com/users/mapbox')
.then((response) => {
console.log(response.data);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
});
// logs:
// => {login: "mapbox", id: 600935, node_id: "MDEyOk9yZ2FuaXphdGlvbjYwMDkzNQ==", avatar_url: "https://avatars1.githubusercontent.com/u/600935?v=4", gravatar_id: "", …}
// => 200
// => OK
// => {x-ratelimit-limit: "60", x-github-media-type: "github.v3", x-ratelimit-remaining: "60", last-modified: "Wed, 01 Aug 2018 02:50:03 GMT", etag: "W/"3062389570cc468e0b474db27046e8c9"", …}
// => {adapter: ƒ, transformRequest: {…}, transformResponse: {…}, timeout: 0, xsrfCookieName: "XSRF-TOKEN", …}
複製程式碼
同時傳送請求
Axios有一個非常有趣的功能,他可以平行傳送多個請求,通過向axios.all()方法傳遞陣列格式的引數。這個方法會返回一個promise物件,並且當所有請求都被resolve時,它才會resolve。下面是個簡單的例子:
// execute simultaneous requests
axios.all([
axios.get('https://api.github.com/users/mapbox'),
axios.get('https://api.github.com/users/phantomjs')
])
.then(responseArr => {
//this will be executed only when all requests are complete
console.log('Date created: ', responseArr[0].data.created_at);
console.log('Date created: ', responseArr[1].data.created_at);
});
// logs:
// => Date created: 2011-02-04T19:02:13Z
// => Date created: 2017-04-03T17:25:46Z****
複製程式碼
以上程式碼向GitHub API傳送了兩個請求,然後列印了每個返回值的create_at屬性的值。需要注意的是:如果任何一個請求的被rejected,那麼該promise物件將會立即reject出第一個被reject的promise物件的結果。
為了方便,Axios同樣提供了一個axios.spread()方法,分配響應陣列的屬性給單獨的變數,下面是簡單的使用方法:
axios.all([
axios.get('https://api.github.com/users/mapbox'),
axios.get('https://api.github.com/users/phantomjs')
])
.then(axios.spread((user1, user2) => {
console.log('Date created: ', user1.data.created_at);
console.log('Date created: ', user2.data.created_at);
}));
複製程式碼
這段程式碼的返回值跟上段程式碼相同,唯一的不同就是axios.spread()方法將響應陣列中的值分配給兩個單獨的變數了。
傳送自定義的請求頭
用Axios自定義請求頭非常簡單,只需要簡單傳遞一個配置了請求頭的物件作為最後一個引數即可,如下:
const options = {
headers: {'X-Custom-Header': 'value'}
};
axios.post('/save', { a: 10 }, options);
複製程式碼
轉換請求和響應的格式
預設情況下,Axios自動將請求和響應的格式轉換成JSON,但是它也允許你覆蓋預設行為,重寫定義不同的轉化機制。當API只接受特殊的資料格式,像XML或CSV時,這個功能就非常有用了。
在向伺服器傳送請求前,在config物件中設定transformRequest屬性(注意:這個方法只在PUT,POST,PATCH請求中生效),下面是使用方法:
const options = {
method: 'post',
url: '/login',
data: {
firstName: 'Finn',
lastName: 'Williams'
},
transformRequest: [(data, headers) => {
// transform the data
return data;
}]
};
// send the request
axios(options);
複製程式碼
想要在觸發then()或catch()之前修改響應資料的格式,你只需要設定transformResponse屬性,如下:
const options = {
method: 'post',
url: '/login',
data: {
firstName: 'Finn',
lastName: 'Williams'
},
transformResponse: [(data) => {
// transform the response
return data;
}]
};
// send the request
axios(options);
複製程式碼
攔截請求和響應
攔截HTTP請求是Axios很受歡迎的一個特性,通過這個特性,你可以在自己的應用程式向伺服器傳送請求之前檢查、修改請求(反之亦然),這個方法對於各種隱性的任務(像日誌或者身份驗證)非常有用。
一眼看過去,攔截器的功能很像一個轉換器,但是他們之間有一個非常重要的不同點:轉化器只將資料和頭資訊作為引數接受,攔截器則是接收整個響應物件或請求配置。
你可以用以下方式宣告一個axios攔截器:
// declare a request interceptor
axios.interceptors.request.use(config => {
// perform a task before the request is sent
console.log('Request was sent');
return config;
}, error => {
// handle the error
return Promise.reject(error);
});
// sent a GET request
axios.get('https://api.github.com/users/mapbox')
.then(response => {
console.log(response.data.created_at);
});
複製程式碼
以上程式碼會列印每當傳送這個請求時,控制檯都會列印上面"Request was sent",然後等待,直到伺服器返回響應,此時,就會列印這個賬號在GitHub上的建立時間(response.data.created_at)。使用攔截器後,你就不用再給每個HTTP請求單獨的寫一段重複的程式碼了。
Axios同樣提供了響應的攔截器,讓我們在伺服器嚮應用返回響應時,統一轉換返回值:
// declare a response interceptor
axios.interceptors.response.use((response) => {
// do something with the response data
console.log('Response was received');
return response;
}, error => {
// handle the response error
return Promise.reject(error);
});
// sent a GET request
axios.get('https://api.github.com/users/mapbox')
.then(response => {
console.log(response.data.created_at);
});
複製程式碼
客戶端支援XSRF防禦
Cross-site request forgery (簡稱XSRF,跨站請求偽造)是一種攻擊網路託管應用程式的方法,攻擊者偽裝成合法且受信任的使用者,以影響該應用程式與使用者瀏覽器之間的互動。有很多方法可以執行這種攻擊,包括XMLHttpRequest
幸好,Axios通過允許使用者在發出請求時嵌入額外的認證資訊的方式防禦XSRF,這使伺服器能夠發現來自未授權地址的請求。以下是使用方法:
const options = {
method: 'post',
url: '/login',
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
};
// send the request
axios(options);
複製程式碼
監控POST請求進度
Axios另一個NB的特性是,他可以監控請求的進度。這個功能在我們下載或上傳大檔案時非常有用。Axios文件上提供了例子,但是簡單起見,我們在本教程中使用Axios Progress Bar模組。
首先,我們需要引入相關的指令碼和樣式
<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/nprogress.css" />
<script src="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/index.js"></script>
複製程式碼
然後我們就可以像下面這樣使用進度條啦:
loadProgressBar()
const url = 'https://media.giphy.com/media/C6JQPEUsZUyVq/giphy.gif';
function downloadFile(url) {
axios.get(url)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
downloadFile(url);
複製程式碼
我們可以這樣覆蓋預設樣式:
#nprogress .bar {
background: red !important;
}
#nprogress .peg {
box-shadow: 0 0 10px red, 0 0 5px red !important;
}
#nprogress .spinner-icon {
border-top-color: red !important;
border-left-color: red !important;
}
複製程式碼
取消請求
有些情況下,你可能不關心請求的結果,並要取消已經傳送的請求,這也是可以實現的哦,只需要使用cancelToken。注意,取消請求的功能是在1.5版本新增的,並且基於可取消的promise的提案,下面是使用方法:
const source = axios.CancelToken.source();
axios.get('https://media.giphy.com/media/C6JQPEUsZUyVq/giphy.gif', {
cancelToken: source.token
}).catch(thrown => {
if (axios.isCancel(thrown)) {
console.log(thrown.message);
} else {
// handle error
}
});
// cancel the request (the message parameter is optional)
source.cancel('Request canceled.');
複製程式碼
您還可以通過傳遞執行器函式給CancelToken建構函式來建立CancelToken,如下所示:
onst CancelToken = axios.CancelToken;
let cancel;
axios.get('https://media.giphy.com/media/C6JQPEUsZUyVq/giphy.gif', {
// specify a cancel token
cancelToken: new CancelToken(c => {
// this function will receive a cancel function as a parameter
cancel = c;
})
}).catch(thrown => {
if (axios.isCancel(thrown)) {
console.log(thrown.message);
} else {
// handle error
}
});
// cancel the request
cancel('Request canceled.');
複製程式碼
瀏覽器相容
Axios在瀏覽器相容上是非常有優勢的,即使是IE11也可以很好地相容。
Chrome | Firefox | Safari | Edge | IE |
---|---|---|---|---|
√ | √ | √ | √ | 11 |
結語
在這篇文章中,我們學習了Axios大部分主要的特性,以及他們的使用方法。還有一些文章中沒涉及的內容,感興趣的同學就去官方文件中深入瞭解吧!