目前前端中发送网络请求的方式有很多种:
- 选择一: 传统的Ajax是基于XMLHttpRequest(XHR)
- 选择二: jQuery-Ajax(基本不用了)
- 选择三: Fetch API
- 选择四: axios
Fetch API
Fetch是AJAX的替换方案,基于Promise设计,很好的进行了关注分离,有很大一批人喜欢使用fetch进行项目开发。
但是Fetch的缺点也很明显,首先需要明确的是Fetch是一个low-level(底层)的API,没有帮助你封装好各种各样的功能和实现。比如发送网络请求需要自己来配置Header的Content-Type,不会默认携带cookie等。比如错误处理相对麻烦(只有网络错误才会reject,HTTP状态码404或者500不会被标记为reject)。比如不支持取消一个请求,不能查看一个请求的进度等等。MDN Fetch学习地址:developer.mozilla.org/zh-CN/docs/…
axios
axios是目前前端使用非常广泛的网络请求库,包括Vue作者也是推荐在vue中使用axios。主要特点包括:在浏览器中发送 XMLHttpRequests 请求、在 node.js 中发送 http请求、支持 Promise API、拦截请求和 响应、转换请求和响应数据等等。我们建议使用axios。
安装 与 平时的业务场景
yarn add axios
平时的业务场景
代码演示
import React, { PureComponent } from 'react'
import axios from 'axios'
export default class App extends PureComponent {
constructor(props){
super(props)
this.state = {
products:[]
}
}
//拿到数据
componentDidMount(){
// this.setState({
// products:[...this.state.products,...res]
// })
//1.axios发送基本的网络请求
axios({
url:'http://httpbin.org/get',
params:{
name:'harry',
age:18
}
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
axios({
url:'http://httpbin.org/post',
data:{
name:"lebri",
age:41
},
method:"post"
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
axios.get("http://httpbin.org/get",{
params:{
name:"lilei",
age:30
}
}).then(console.log)
axios.post("http://httpbin.org/post",{
name:"lucy",age:28
}).then(console.log)
}
render() {
return (
<div>App</div>
)
}
}
使用async await
async componentDidMount(){
// this.setState({
// products:[...this.state.products,...res]
// })
//1.axios发送基本的网络请求
const result = await axios.get("http://httpbin.org/get",{
params:{
name:"lilei",
age:30
}
})
console.log(result);
}
async await方式得通过try catch可以拿到错误信息。
try {
const result = await axios.get("http://httpbin.org/get",{
params:{
name:"lilei",
age:30
}
})
console.log(result);
} catch (error) {
console.log(error);
}
axios.all可以合并网络请求
const request1 = axios({
url: "/get",
params: { name: "why", age: 18 }
})
const request2 = axios({
url: "/post",
data: { name: "kobe", age: 40 },
method: "post"
})
axios.all([request1, request2]).then(([res1, res2]) => { //对数组解构
console.log(res1, res2);
});
axios的默认配置
在index.js里加入
// 7.默认配置
axios.defaults.baseURL = "https://httpbin.org";
axios.defaults.timeout = 5000;
axios.defaults.headers.common["token"] = "dafdafadfadfadfas";
// axios.defaults.headers.post["Content-Type"] = "application/text";
axios创建新的实例
在开发中我们可能会请求多台服务器,这样就可以创建多个实例。
使用axios.create创建实例,并用变量接受。
const instance1 = axios.create({
baseURL: "http://coderwhy.xyz",
timeout: 5000,
headers: {
}
})
const instance2 = axios.create({
baseURL: "http://baidu.xyz",
timeout: 10000,
headers: {
}
})
axios 请求和响应拦截
axios支持在发送请求之前对请求拦截。
响应拦截一般用于处理错误。
// 请求拦截
axios.interceptors.request.use(config => {
// 1.发送网络请求时, 在界面的中间位置显示Loading的组件
// 2.某一些请求要求用户必须携带token, 如果没有携带, 那么直接跳转到登录页面
// 3.params/data序列化的操作
console.log("请求被拦截");
return config; //配置信息一定要return
}, err => {
});
axios.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:
console.log("其他错误信息");
}
}
return err;
});
对axios进行二次封装
axios最好自己手动封装。
//config.js
const devBaseURL = "https://httpbin.org"
const proBaseURL = "https://xxxxxx.org"
//判断是不是开发环境 (开发/生成)
export const BASE_URL = process.env.NODE_ENV === 'development' ? devBaseURL:proBaseURL;
export const TIMEOUT = 5000
//config.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 => {
// 1.发送网络请求时, 在界面的中间位置显示Loading的组件
// 2.某一些请求要求用户必须携带token, 如果没有携带, 那么直接跳转到登录页面
// 3.params/data序列化的操作
console.log("请求被拦截");
return config;
}, err => {
});
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:
console.log("其他错误信息");
}
}
return err;
});
export default instance;
如果想要使用
import request from '@network/request' //导入
request({
url:''
........
.......
})
自己也可以根据需求再次封装。