Axios
Axios
1. Axios 简介
Axios 是一个基于 promise 网络请求库,作用于 node.js 和浏览器中。 它是 isomorphic 的(同一套代码可以运行在浏览器和 node.js 中)。在服务端它使用原生 node.js http 模块,而在客户端则使用 XMLHttpRequest。
2. 特性
- 从浏览器创建 XMLHttpRequests;
- 从 node.js 创建 http 请求;
- 支持 Promise API;
- 拦截请求和响应;
- 转换请求和响应数据;
- 取消请求;
- 自动转换 JSON 数据;
- 客户端支持防御 XSRF;
3. 封装 Axios
由于 axios 是一个基于 xhr+promise 的异步 ajax 请求库,所以可以先单纯的封装一个:
function axios(config){
// 将请求方式全部转为大写
const method = (config.method || "get").toUpperCase();
// 返回 Promise
return new Promise((resolve,reject) => {
// 声明 xhr
const xhr = new XMLHttpRequest();
// 定义一个 onreadystatechange 监听事件
xhr.onreadystatechange = function () {
// 数据全部加载完成
if(xhr.readyState === 4){
// 判断状态码是否正确
if(xhr.status >= 200 && xhr.status < 300){
// 得到响应体的内容
const data = JSON.parse(xhr.responseText);
// 得到响应头
const headers = xhr.getAllResponseHeaders();
// request 即是 xhr
const request = xhr;
// 状态码
const status = xhr.status;
// 状态码的说明
const statusText = xhr.statusText;
resolve({
config,
data,
headers,
request,
status,
statusText
});
}
else{
reject("请求失败" + xhr.status + xhr.statusText);
}
}
}
// 判断是否拥有 params, 且类型为 object
if(typeof config.params === "object"){
// 将 object 转为 urlencoded
const arr = Object.keys(config.params);
const arr2 = arr.map(v => v + "=" + config.params[v]);
const url = arr2.join("&");
config.url += "?" + url;
}
xhr.open(method, config.url);
// post put patch
if(method === "POST" || method === "PUT" || method === "PATCH"){
if(typeof config.data === "object")
xhr.setRequestHeader("content-type", "application/json");
else if(typeof config.data === "string")
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhr.send(JSON.stringify(config.data));
}
else{
xhr.send();
}
})
}
以上代码实现了 axios(config) 直接发起请求,例如:
axios({
method: "delete",
url: "data.json"
}).then(res => console.log(res))
但是,如果想通过 axios.get(url[, config])、axios.delete(url[, config])、axios.post(url[, data[, config]]) 等请求方式就行不通了。
4. 封装 request
通过阅读源码得到一些启示:源码中有一个名为 Axios 的构造函数,而我们的 xhr + promise 封装在 Axios.prototype.request 函数中。另外所使用的 axios.get、axios.post 等也都是定义在 Axios.prototype 中。
根据这些启示将代码调整为:
// 构造函数
function Axios(){
}
Axios.prototype.request = function (config) {
// 将请求方式全部转为大写
const method = (config.method || "get").toUpperCase();
// 返回Promise
return new Promise((resolve,reject)=>{
// 声明xhr
const xhr = new XMLHttpRequest();
// 定义一个onreadystatechange监听事件
xhr.onreadystatechange = function () {
// 数据全部加载完成
if(xhr.readyState === 4){
// 判断状态码是否正确
if(xhr.status >= 200 && xhr.status < 300){
// 得到响应体的内容
const data = JSON.parse(xhr.responseText);
// 得到响应头
const headers = xhr.getAllResponseHeaders();
// request 即是 xhr
const request = xhr;
// 状态码
const status = xhr.status;
// 状态码的说明
const statusText = xhr.statusText;
resolve({
config,
data,
headers,
request,
status,
statusText
});
}
else{
reject("请求失败" + xhr.status + xhr.statusText);
}
}
}
// http://127.0.0.1/two?a=1&b=2
// 判断是否拥有 params, 且类型为 object
if(typeof config.params === "object"){
// 将 object 转为 urlencoded
const arr = Object.keys(config.params);
const arr2 = arr.map(v => v + "=" + config.params[v]);
const url = arr2.join("&");
config.url += "?" + url;
}
xhr.open(method,config.url);
// post put patch
if(method === "POST" || method === "PUT" || method === "PATCH"){
if(typeof config.data === "object")
xhr.setRequestHeader("content-type","application/json");
else if(typeof config.data === "string")
xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
xhr.send(JSON.stringify(config.data));
}
else{
xhr.send();
}
})
}
Axios.prototype.get = function (url, config) {
return this.request({
method: "get",
url,
...config
});
}
Axios.prototype.post = function (url, data) {
return this.request({
url,
method: "post",
data
})
}
// 其它请求 delete, patch 省略
export default new Axios();
这样可以通过 axios.get(url[, config])、axios.post(url[, data[, config]]) 请求数据了。
import axios from "./Axios.js";
axios.post("data.json", {
a:1,
b:2
}).then(res=>{
console.log(res);
})
axios.get("data.json",{
params:{
a:1,
b:2
}
}).then(res=>{
console.log(res);
})
计算机网络 文章被收录于专栏
计算机网络