概述
何为axios? 个人理解为【Ajax IO Stream】
一款棒棒的、使用广泛的、基于Promise的、具有请求拦截功能的、具有请求撤销功能的、方便做关联并发的、配置丰富的ajax库;
安装依赖
npm i axios
注意事项
注意请求成功时,res.data才是真正从服务端返回的数据,其余信息为axios框架自行封装的一些信息
发起GET请求
axios
.get(
"https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/goods/list/1"
)
.then(function (res) {
console.log("res=", res);
})
.catch(function (err) {
console.log("err=", err);
});
发起POST请求
携带JSON数据
axios
.post(
"https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/login",
{
username: "admin",
password: "123456",
}
)
.then(function (res) {
console.log("res=", res);
response.value = res.data;
error.value = "暂无数据";
})
.catch(function (err) {
console.log("err=", err);
error.value = err;
response.value = "暂无数据";
});
携带表单数据
const params = new URLSearchParams();
params.append("username", "admin");
params.append("password", "123456");
axios
.post(
"https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/login",
params
)
.then(function (res) {
console.log("res=", res);
})
.catch(function (err) {
console.log("err=", err);
});
玩一下async/await
const postForm = async () => {
try {
const params = new URLSearchParams();
params.append("username", "admin");
params.append("password", "123456");
const { data } = await axios.post("http://httpbin.org/post", params);
response.value = data;
error.value = "暂无数据";
} catch (err) {
error.value = err;
response.value = "暂无数据";
}
};
合并多个并发请求的数据
function getOdd() {
return axios.get(
"https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/goods/list/1"
);
}
function getEven() {
return axios.get(
"https://www.fastmock.site/mock/2f84b6ecf17efe9acc0637e460d67bce/api/goods/list/2"
);
}
axios
.all([getOdd(), getEven()])
.then(
axios.spread(function ({ data: odd }, { data: even }) {
// 两个请求现在都执行完成
console.log("odd", odd);
console.log("even", even);
response.value = odd.data.concat(even.data);
error.value = "暂无数据";
console.log(response.value.length);
})
)
.catch((err) => {
console.log("err=", err);
error.value = err;
response.value = "暂无数据";
});
配置不同的axios实例(用于请求不同的业务)
const instance = axios.create({
baseURL: "http://httpbin.org",
timeout: 3000,
headers: { "X-Custom-Header": "foobar" },
});
/* 发起请求 */
instance
.post("/post", {
username: "admin",
password: "123456",
})
.then((data) => (response.value = data))
.catch((err) => (error.value = err));
配置拦截器
拦截器可以统一对所有请求和响应做预处理
// 添加请求拦截器
instance.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么:为所有请求配置请求头authorization 令其携带身份认证token
config.headers["authorization"] = "Bearer mytoken";
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
instance.interceptors.response.use(
function (response) {
// 对响应数据做点什么:从响应中剥离出【服务器端返回的数据】 过滤掉axios自行封装的信息
return response.data;
},
function (error) {
// 对响应错误做点什么
return Promise.reject(error);
}
);
axios请求的取消
一个CancelToken可以取消多个请求:
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios
.get("/user/12345", {
cancelToken: source.token,
})
.catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log("Request canceled", thrown.message);
} else {
// 处理错误
}
});
axios.post(
"/user/12345",
{
name: "new name",
},
{
cancelToken: source.token,
}
);
// 必要时取消请求(message 参数是可选的)
// 例如离开当前页面前取消未完成的请求
source.cancel("Operation canceled by the user.");
经典的三层封装
第一层/实例层:配置请求实例与拦截器,导出请求实例
const instance = axios.create({
// baseURL: "http://localhost:9000/api",
baseURL: '/api',
timeout: 3000
})
// 添加请求拦截器
instance.interceptors.request.use(
function(config) {
// 在发送请求之前做些什么
config.headers['Authorization'] = `Bearer ${getToken()}`
return config
},
function(error) {
// 对请求错误做些什么
return Promise.reject(error)
}
)
// 添加响应拦截器
instance.interceptors.response.use(
function(response) {
// 对响应数据做点什么
return response.data
},
function(error) {
// 对响应错误做点什么
return Promise.reject(error)
}
)
第二层/操作层:封装并导出通用增删改查方法
export async function doPost(url, data, conf) {
try {
const ret = await instance.post(url, data, conf)
return ret
} catch (error) {
handleErr(`doPost@${url}`, error)
}
}
export function doDelete(url,conf) {
return instance.delete(url, conf)
}
export function doPut(url, data, conf) {
return instance.put(url, data, conf)
}
export async function doGet(url, conf) {
try {
const ret = await instance.get(url, conf)
return ret
} catch (error) {
handleErr(`doGet@${url}`, error)
}
}
第三层/业务层:业务逻辑请求封装
import { doDelete, doGet, doPost, doPut } from "../network/request";
export async function addGoods(goods) {
return await doPost("/goods/0", goods);
}
export async function deleteGoods(goods) {
return await doDelete(`/goods/${goods._id}`);
}
export async function updateGoods(goods) {
console.log("updateGoods", goods);
let gid = goods._id;
delete goods._id;
return await doPut(`/goods/${gid}`, goods);
}
export async function getGoodsByPage(page) {
const data = await doGet(`/goods/list/${page % 2 === 1 ? 1 : 2}`);
return new Promise((resolve, reject) => {
setTimeout(() => {
// return data;
resolve(data);
}, 2000);
});
}
写在最后
如果喜欢,我们还可以给所有Vue/React组件来一个useAxios的小hook!
大致实现思路如下:
- 让url作为入参,返回一组响应式数据{loading,data,error};
- 组件一挂载就立即请求数据,此时loading为true;
- 请求完毕后,data与error必是一实一空,loading为false;
- 组件卸载时,如果loading为true,则自动取消未完成请求;