一、前端网络请求的选择
1. 传统的Ajax是基于XMLHttpRequest(XHR)
缺点: 配置和调用方式等非常混乱, 编码麻烦
2. 使用 jQuery-Ajax
相对于传统的Ajax非常好用.
缺点: jQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理
3. Fetch API
Fetch是AJAX的替换方案,基于Promise设计,很好的进行了关注分离,有很大一批人喜欢使用fetch进行项目开发
缺点:
-
首先需要明确的是Fetch是一个 low-level(底层)的API,没有帮助你封装好各种各样的功能 和实现;
-
比如发送网络请求需要自己来配置Header的Content-Type,不会默认携带cookie等;
-
比如错误处理相对麻烦(只有网络错误才会reject,HTTP状态码404或者500不会被标记为reject);
-
不支持取消一个请求,不能查看一个请求的进度等等
4. axios
axios 是目前前端使用非常广泛的网络请求库,包括 Vue 作者也是推荐在 Vue 中使用 axios;
axios 特点:
- 基于promise用于浏览器和node.js的http客户端
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和响应
- 自动转换JSON数据
- 能转换请求和响应数据
二、axios 基本使用
- axios(config)
- axios.request(config)
- axios.get(url [, config])
- axios.delete(url [, config])
- axios.head(url [, config])
- axios.post(url [, data[, config]])
- axios.put(url [, data[, config]])
- axios.put(url [, data[, config]])
1. axios(config)
1.1 get
1. 通过传统的url 以 ? 的形式传递参数
axios({
url: 'http://httpbin.org/get?id=123'
})
2. restful 形式传递参数
axios({
url: 'http://httpbin.org/get/123',
})
3. 通过 params 形式传递参数
axios({
url: 'http://httpbin.org/get',
params: {
name: 'why',
age: 18
}
})
delete 和 get 请求传参方式相同
1.2 post
post 和 put 请求传参方式相同
axios({
url: 'http://httpbin.org/post',
data: {
name: 'kobe',
age: 18
},
method: 'post'
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
1.3 async await 异常处理
使用 try catch 来捕获异常
async componentDidMount() {
try {
const result = await axios.get("http://httpbin.org/get", {
params: {
name: "lilei",
age: 30,
},
});
console.log(result);
} catch (err) {
console.log(err);
}
}
2. axios.request(config)
axios.request({
url: "http://httpbin.org/get",
params: {
name: "why",
age: 18,
},
})
3. axios.get(url [, config])
- 通过传统的url 以 ? 的形式传递参数
- restful 形式传递参数
- 通过 params 形式传递参数
axios.get('http://localhost:3000/axios', {
params: {
id: 789
}
}).then(function(ret){
console.log(ret.data)
})
4. axios.delete(url[, config])
delete 请求传参的形式和 get 请求一样
axios.delete('http://localhost:3000/axios', {
params: {
id: 111
}
}).then(function(ret){
console.log(ret.data)
})
6. axios.post(url[, data[, config]])
6.1 通过选项传递参数
axios.post('http://localhost:3000/axios', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
6.2 通过 URLSearchParams 传递参数
var params = new URLSearchParams();
params.append('uname', 'zhangsan');
params.append('pwd', '111');
axios.post('http://localhost:3000/axios', params).then(function(ret){
console.log(ret.data)
})
7. axios.put(url[, data[, config]])
axios delete 请求传参的形式和 get 请求一样
axios.put('http://localhost:3000/axios/123', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
三、 axios 配置信息
1. axios 全局配置
1. 默认请求接口
axios.defaults.baseURL = 'https://api.example.com';
2. 配置超时时间
axios.defaults.timeout = 2500;
3. 配置公共的请求头
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
4. 配置公共的 post 的 Content-Type
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
2. 自定义实例配置
const instance = axios.create({
baseURL: BASE_URL,
timeout: TIMEOUT
});
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN
四、 axios 拦截器
1. 请求拦截器
请求拦截器的作用是在请求发送前进行一些操作
1.1 使用场景
- 发送网络请求时,在页面中添加一个loading组件作为动画
- 某一些请求要求用户必须携带,如果没有携带,那么直接跳转到登录页面
- 对某些请求参数进行序列化
1.2 使用方法
axios.interceptors.request.use(回调函数1, 回调函数2)
axios.interceptors.request.use(config => {
// 1. 发送网络请求,在界面的中间位置显示 Loading 的组件
// 2. 某一些请求要求用户必须携带,如果没有携带,那么直接跳转到登录页面
// 3. parms/data 序列化的操作
// 这里一定要return 否则配置不成功
return config;
}, function(err){
// 4. 对请求错误做点什么
console.log(err)
});
2. 请求拦截
2.1 使用场景
- 响应拦截中可以对结果进行二次处理(比如服务器真正返回的数据其实是在response的data中)
- 对于错误信息进行判断,根据不同的状态进行不同的处理;
2.2 使用方法
axios.interceptors.response.use(回调函数1, 回调函数2)
axios.interceptors.response.use(res => {
return res.data;
}, err => {
if (err && err.response) {
switch(err.response.status) {
case 400:
console.log("请求错误");
case 401:
console.log("未授权访问");
}
}
})
四、对 axios 进行二次封装
1. 为什么要二次封装?
直接使用 axios, 如果 axios 出现 bug 无法修复, 这时我们会寻找一个新的网络请求库或者自己进行封装一个, 但项目中有多处依赖 axios, 不利于修改,所以我们就要对 axios 进行二次封装
2. 封装 axios
// config.js 配置文件
const devBaseURL = "http://123.207.32.32:9001";
const proBaseURL = "http://123.207.32.32:9001";
export const BASE_URL = process.env.NODE_ENV === 'development' ? devBaseURL : proBaseURL;
export const TIMEOUT = 5000;
// request.js
import axios from 'axios';
// 导入配置
import { BASE_URL, TIMEOUT } from './config';
// 自定义实例默认配置
const instance = axios.create({
baseURL: BASE_URL,
timeout: TIMEOUT
})
// 请求拦截
instance.interceptors.request.use(config => {
return config;
})
// 响应拦截
instance.interceptors.response.use(res => {
return res.data;
}, err => {
if (err && err.response) {
switch(err.response.status) {
case 400:
console.log('请求错误');
break;
case 401:
console.log('未授权访问');
break;
default:
break;
}
}
});
// 导出实例
export default instance;
// 引入实例
import request from "./request";
// 发送请求
request({
url: '/top/list',
params: {
idx
}
}).then(res => {
console.log(res);
});