fetch是浏览器内置的类,进行数据请求,天生就是基于promise进行管理的
axios是基于ajax和promise进行封装的库
下面是axios封装基本需求
// 二次封装axios import axios from 'axios'; import { config } from 'process'; import qs from qs; // 根据环境变量区分接口的默认地址 switch(process.env.NODE_ENV){ case "production": //生产环境 axios.defaults.baseURL = "http://api.yanggengzhen.com"; break; case "test": //测试环境 axios.defaults.baseURL = "http://192.168.20.12:8080"; break; default: axios.defaults.baseURL = "http://127.0.0.1:3000" } // 设置超时时间和跨域是否允许携带凭证 axios.defaults.timeout = 10000; axios.defaults.withCredentials = true; // 设置POST请求头,告知服务器请求主体的数据格式(看服务器要求什么格式) // 就算是post请求有些人会要求以xxx=xxx&xxx=xxx的形式传参,这就是x-www-form-urlencoded格式 axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded'; // 将传参的json格式的data转化为xxx=xxx&xxx=xxx axios.defaults.transformRequest = data => { qs.stringify(data)} //设置请求拦截器 // 客户端发送请求 ->[请求拦截器] -> 服务器 // TOKEN校验(JWT):接收服务器返回的token,存储到vuex/本地存储中,每一次向服务器发请求,我们应该把token带上 axios.interceptors.request.use( config =>{ // config表示请求头的配置项 // 携带上token let token = localStorage.getItem('token'); token && (config.headers.Authorization = token); return config; //不返回config的话后端接收一片空白 },error=>{ return Promise.reject(error); }) // 自己设置哪些状态码表示成功,哪些表示失败(只要是返回2xx或者3xx都算请求成功,响应拦截器就会走第一个,否则走error) axios.default.validateStatus = function (status){ //状态码 return /^(2|3)d{2}$/.test(status); } // 响应拦截器 // 服务器返回信息 -> [拦截的统一请求] ->客户端js获取到信息 axios.interceptors.response.use(response=>{ return response.data; //只拿响应主题内容 },error=>{ let { response } = error; if(response){ // 服务器有返回结果(常用的错误状态码) switch (response.status){ case 401: //当前请求需要用户验证(一般是未登录)(权限) break; // 一般操作是跳转路由或者弹出蒙层 case 403: //服务器已经理解请求,但是拒绝执行它(一般是token过期) localStorage.removeItem('token') // 跳转到登陆页 break; case 404: //找不到页面或者请求失败,请求所希望得到的资源未被放在服务器上发现 break; } return Promise.reject(response) }else{ // 服务器连结果都没有返回 if(!window.navigator.onLine){ // 断网处理:可以跳转到断网页面(把路由导进来,重新连接的时候可以go(-1),路由跳转,路由信息保存) return } return Promise.reject(error) //服务器返回结果都没有,并且也没有断网,此时应该是服务端的问题 } }) export default axios;
fetch封装库基本需求
// fetch import qs from 'qs' // 根据环境变量进行接口区分 let baseUrl = ''; let baseURLArr = [ { type:'development', url:'http://127.0.0.1:9000' }, { type:'test', url:'http://192.168.20.15:9000' }, { type:'production', url:'http://api.yanggengzhen.com' } ] baseURLArr.forEach(item=>{ if(process.env.NODE_ENV === item.type){ baseUrl = item.url } }) // 前端请求的时候,传参的时候转变为url+? query // request(url,{ // params:{ // } // }) export default function request(url,options={}){ url = baseUrl + url; //请求的url ,配置项,如果不传,默认为空对象 // get系列请求的处理 !options.methods?options.methods = 'GET':null; if(options.hasOwnProperty('params')){ if(/^(GET|DELETE|HEAD|OPTIONS)$/i.test(options.methods)){ //判断是否是get请求 const ask = url.includes('?')?'&':'?'; url += `${ask}${qs.stringify(params)}` } delete options.params; } // 合并配置项 options = Object.assign({ //允许跨域携带资源凭证same-origin同源可以 omit都拒绝 credentials:'include', // 设置请求头 header:{} },options); options.headers.Accept = 'application/json'; // token的校验 const token = localStorage.getItem('token'); token && (options.header.Authorization = token); // post请求的处理 if(/^(POST|PUT)$/i.test(options.methods)){ !options.type ? options.type = 'urlencoded' :null; if(options.type === 'urlencoded'){ options.headers['Content-Type'] = 'application/x-www-form-urlencoded'; options.body = qs.stringify(options.body); } if(options.type === 'json'){ options.headers['Content-Type'] = 'application/json'; options.body = JSON.stringify(options.body); } } return fecth(url,options).then(response =>{ // fecth和axios ajax的区别:不论服务器返回什么,都会成功触发.then //返回的结果可能是非200状态码 if(!/^(2|3)d{2}$/.test(response.status)){ switch (response.status) { case 401: // 当前请求需要用户验证(一般是未登录) break; case 403: //服务器已经理解请求,但是拒绝执行它(一般是token过期) break; case 404: //请求失败,请求所希望得到的资源未被再服务器上发现 break; } return Promise.reject(response) } }).catch(error => { //断网处理 if(!window.navigator.onLine){ //断开网络了。可以让其跳转到断网页面 return; } return Promise.reject(error) }) }
最后制作成统一接口export出去,再到vue原型链上挂载属性,调用即可