背景
- 以前写项目从来不封装这玩意,后来发现别人写项目都这么搞,于是照着做了个axios与fetch的
- 通过对fetch的封装,可以发现,实际发送请求就那一下,拦截器配置的实质其实就是在请求前做操作或者收到响应后做操作。我一开始听axios的拦截器以为是个多高端的东西。。。这样手写axios也就很容易搞,实际请求就是用ajax发,自己写个类然后配置拦截器即可。后面准备写一篇手写axios。
代码
- 由于这封装多用于项目,所以我结合了webpack进行操作。webpack的配置就不说了,直接放代码。
axios.js
import axios from 'axios'
import qs from 'qs'
//配置url
switch(process.env.NODE_ENV){
case "production"://生产自己配
axios.defaults.baseURL = "http://127.0.0.1:8080";
break;
case "development":
axios.defaults.baseURL = "http://127.0.0.1:8080";
break;
default:
axios.defaults.baseURL = "http://127.0.0.1:8080"
}
//设置超时时间
axios.defaults.timeout=10000
//设置是否允许跨域携带资源凭证
axios.defaults.withCredentials = true
//设置post请求头,告知服务器请求主体的数据格式 //很多老后台都是此格式,json也比较多。此格式跟get传参格式一样。
axios.defaults.headers['Content-Type']="application/x-www-form-urlencoded"
//不使用上面格式,data自行处理。
axios.defaults.transformRequest = data => qs.stringify(data)
//配置请求拦截器 config就是发请求的配置
axios.interceptors.request.use((config)=>{
//查找token并带上请求
let token = localStorage.getItem('token')
token&&(config.headers.Authorization =token)
return config
},err=>Promise.reject(err))
//自定义响应成功http状态码
axios.defaults.validateStatus=status=>{
return /^(2|3)\d{2}$/.test(status)
}
//配置相应拦截器
axios.interceptors.response.use((res)=>{
//一般只要把返回数据拿出来即可。避免每次都取数据要点data
return res.data
},err=>{
let {response}=err
if(response){//有结果
switch(response.status){
case 401://请求需要验证
break;
case 403://一般为token session过期,服务器拒绝
localStorage.removeItem(token)
break;
case 404: //找不到页面
break;
default:
return
}
}else{//服务器没返回
if(!window.navigator.onLine){
//断网处理 配置断网页面
return
}
return Promise.reject(err)
}
})
export default axios
fetch.js
import qs from 'qs'
let baseURL = ''
//配置url
switch(process.env.NODE_ENV){
case "production"://生产自己配
baseURL = "http://127.0.0.1:8080";
break;
case "development":
baseURL = "http://127.0.0.1:8080";
break;
default:
baseURL = "http://127.0.0.1:8080"
}
export default function request(url,option={}) {
url = baseURL+url;
!option.method?option.method='get':null
if(option.hasOwnProperty('params')){//i表示不区分大小写,参数有可能写配置项而不是url
if(/^(GET|DELETE|HEAD|OPTIONS)$/i.test(option.method)){
//如果url有问号,说明这些参数是另加,用&连接,如果没有,就上问号连接
const ask =url.includes('?')?'&':'?';
url +=`${ask}${qs.stringify(option.params)}`
}
delete option.params
}
//合并配置
option = Object.assign({
crendentials:"include",//same-origin同源才可以,omit拒绝携带资源凭证
headers:{}
},option)
const token = localStorage.getItem('token')
token && (option.headers.Authorization=token)
//post
if(/^(POST|PUT)$/i.test(option.method)){
!option.type?option.type='urlencoded':null
//判断类型加上请求头
if(option.type==='urlencoded'){
option.headers['Content-Type']='application/x-www-form-urlencoded'
option.body = qs.stringify(option.body)
}
if(option.type==='json'){
option.headers['Content-Type']='application/json'
option.body = JSON.stringify(option.body)
}
}
return fetch(url,option).then(res=>{
if(!/^(2|3)\d{2}$/.test(res.status)){
switch(res.status){
case 401://请求需要验证
break;
case 403://一般为token session过期,服务器拒绝
localStorage.removeItem(token)
break;
case 404: //找不到页面
break;
default:
return
}
}
return res.json()
}).catch(err=>{
if(!window.navigator.onLine){
//断网
return
}else{
return Promise.reject(err)
}
})
}
- 然后写了个api文件在index.js里导入进行测试:
api.js
import axios from './axios'
import request from './fetch'
export function login() {
return axios.post('/post', {
name: 'axiospost'
})
}
export function test() {
return request('/get', {
method: 'get',
params: { name: 'fetch' }
})
}
export function fetchpost() {
return request('/post', {
method: 'post',
type: 'urlencoded',
body: {
name: 'fetchpost'
}
})
}
export function axiosget() {
return axios.get("/get", {
params: {
name: "axiosget"
}
})
}
index.js
import *as api from './api'
api.login().then((res)=>console.log(res))
api.test().then((res)=>console.log(res))
api.axiosget().then((res)=>console.log(res))
api.fetchpost().then((res)=>console.log(res))
- 如果有同学懒得配webpack或者后端的可以使用此仓库。里面配了个基本配置,后端使用直接node运行server.js即可。