基于axios二次封装网络请求
程序员文章站
2024-03-07 14:40:57
...
基于axios二次封装网络请求
本套网络请求基于axios的二次封装,用到了vuex(断网及其他错误的标识)、vue-router(页面跳转)和element-UI的一些交互;封装采用模块化思想,各个文件的功能单一,大大降低了耦合性。
请求亮点:
1、可控制请求时loading的样式及是否需要显示loading;
2、请求错误时的统一提示
3、请求超时、断网、请求报错的统一处理
4、请求可以有多个域名
5、请求接口的统一管理
6、封装采用模块化思想
一、文件目录:
二、各文件介绍
1、/http/axios.js
import axios from "axios"
import httpCode from './httpCode';
import router from '../router/index';
import store from '../store/index';
//创建axios实例
var instance = axios.create({ timeout: 1000 * 20 });
// 请求拦截器
instance.interceptors.request.use(
config => {
// 登录流程控制中 根据本地是否存在token判断用户的登录情况
const token = store.state.token;
token && (config.headers.Authorization = token);
return config;
},
error => Promise.error(error)
)
// 响应拦截器
instance.interceptors.response.use(
// 请求成功
res => {
res.status === 200 ? Promise.resolve(res) : Promise.reject(res)
//请求成功后改变network状态为true
store.dispatch('changeNetwork', true);
},
// 请求失败
error => {
const { response } = error;
if (response) {
//请求已发出 不在2xx的范围
httpCode(response.status)
return Promise.reject(response);
} else {
//处理断网的情况 请求超时或断网时 更新state的network状态
router.push({ path: '/network' })
//请求失败后改变network状态为false
store.dispatch('changeNetwork', false);
}
});
export default instance
2、/http/httpCode.js
import router from '../router/index';
import store from '../store/index';
import { Notification } from 'element-ui';
/**
* 跳转登录页
* 携带当前页面路由,以期在登录页面完成登录后返回当前页面
*/
const toLogin = () => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}
/**
* 跳转404页面
* 携带当前页面路由,以期在登录页面完成登录后返回当前页面
*/
const to404Error = () => {
router.replace({
name: '404Error',
query: {
redirect: router.currentRoute.fullPath
}
});
}
/**
* 请求失败后的错误统一处理
* @param {请求失败的状态码} status
*/
export default function (code) {
// 请求错误信息
let errorInfo = ''
//判断参数来输出错误信息
switch (code) {
case 400:
errorInfo = "错误请求";
break;
case 401:
//跳转到登录页
toLogin();
errorInfo = '访问令牌无效或已过期';
break;
case 403:
//拒绝时的参数
localStorage.removeItem('token');
store.dispatch('loginSuccess', null);
setTimeout(() => {
toLogin();
}, 1000);
errorInfo = '登录过期,请重新登录';
break;
case 404:
to404Error()
errorInfo = '请求资源不存在';
break;
case 405:
errorInfo = '请求方法未允许';
break;
case 408:
errorInfo = '请求超时';
break;
case 500:
errorInfo = '访问服务失败';
break;
case 501:
errorInfo = '未实现';
break;
case 502:
errorInfo = '无效网关';
break;
case 503:
errorInfo = '服务不可用';
break;
default:
errorInfo = "连接错误";
break;
}
Notification.error({
title: "提示",
message: errorInfo
})
}
3、/http/base.js
/**
* 域名统一管理
*/
//测试域名
export const testUrl = "https://abnercapi.cdcyy.net"
//正式域名
export const path = "https://abnercapi.cdcyy.net"
4、/http/index.js
import axios from './axios';
import { Loading } from 'element-ui';
import { Notification } from 'element-ui';
//Loading 参数
let obj = {
lock: true,
text: '加载中...',
target: "#main",
spinner: 'el-icon-loading'
}
/**
* POST请求
* @param {请求地址} url
* @param {请求参数} params
* @param {其他参数,第一项为是否需要Loading} params2
*/
export const post = function (url, params, ...params2) {
if (params2 && params2.length === 0) {
//当未传入其他参数时 默认有loading 且默认loading下方的文字文默认“加载中...”
return request("POST", url, params, true)
} else if (params2[0].isLoading) {
//当传入其他参数时 第一个参数的第一项为是否需要loading 当“isLoading”字段为“true”时 默认需要更换loading下方的文字”
obj.text = params2[0].loadingText ? params2[0].loadingText : "加载中..."
return request("POST", url, params, true)
} else {
//当传入其他参数时 其他情况一律处理为不要loading
return request("POST", url, params, true)
}
}
/**
* GET请求
* @param {请求地址} url
* @param {请求参数} params
* @param {其他参数,第一项为是否需要Loading} params2
*/
export const get = function (url, params, ...params2) {
if (params2 && params2.length === 0) {
//当未传入其他参数时 默认有loading 且默认loading下方的文字文默认“加载中...”
return request("GET", url, params, true)
} else if (params2[0].isLoading) {
//当传入其他参数时 第一个参数的第一项为是否需要loading 当“isLoading”字段为“true”时 默认需要更换loading下方的文字”
obj.text = params2[0].loadingText ? params2[0].loadingText : "加载中..."
return request("GET", url, params, true)
} else {
//当传入其他参数时 其他情况一律处理为不要loading
return request("GET", url, params, true)
}
}
/**
* 网络请求
* @param {请求方法} method
* @param {请求地址} url
* @param {请求参数} params
* @param {loading状态} status
*/
function request(method, url, params, status) {
let loading
if (status) {
loading = Loading.service(obj);
}
return new Promise((resolve, reject) => {
axios({
method: method,
url: url,
data: params
})
.then(res => {
//停止Loading
if (status) loading.close();
//返回数据的操作 可根据后台返回的数据结构自行处理
if (res && res.data && res.data.status) {
resolve(res.data)
} else {
resolve(false)
Notification({
title: "提示",
message: res.data.message,
type: "error"
})
}
})
.catch(err => {
//停止Loading
if (status) loading.close();
reject(err)
})
})
}
5、/api/orderReq.js
/*
* 订单模块接口列表
*/
import { testUrl } from '@/http/base'; // 导入接口域名列表
import { post, get } from '@/http/index'; // 导入http中创建的axios实例
import qs from 'qs'; //参数序列化 qs.stringify(params)
const order = {
//获取列表
getList(params) {
//loading参数配置
let loadOpt = { isLoading: true, loadingText: "我要加载..." }
return post(`${testUrl}xxxxxxx`, {}, loadOpt);
},
//更新
updataList(params) { },
//删除列表
delectList(params) { },
//添加列表
setList(params) { },
}
export default order;
6、/api/index.js
/**
* 接口统一管理
*/
import order from '@/api/orderReq';
export default {
order,
}
三、挂载到vue原型上
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import api from './api/index'
Vue.prototype.$api = api;
Vue.config.productionTip = false
new Vue({
router,
store,
render: function (h) { return h(App) }
}).$mount('#app')
四、页面使用(例)
this.$api.order.getList(obj).then((res) => {
console.log(res);
});
五、断网处理页面
<template>
<div class="container">
<h3>我没网了</h3>
<el-button type="primary" @click="onRefresh()">刷新</el-button>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "App",
inject: ["reload"],
computed: {
...mapGetters(["getNetwork"]),
},
created() {
//当请求成功就不能到该页面
if (this.getNetwork) this.$router.go(-1);
},
methods: {
//返回之前的页面再请求一次判断是否请求成功
onRefresh() {
this.$router.go(-1);
},
},
};
</script>
<style lang="less" scoped>
.container {
text-align: center;
}
</style>
六、404页面
<template>
<div class="container">
<h3>我TM居然是一个没人要的页面</h3>
<el-button type="primary" @click="$router.push('/home')">返回首页</el-button>
<el-button type="primary" @click="onRefresh()">刷新</el-button>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "App",
inject: ["reload"],
computed: {
...mapGetters([""]),
},
methods: {
//返回之前的页面再请求一次判断是否请求成功
onRefresh() {
this.$router.go(-1);
},
},
};
</script>
<style lang="less" scoped>
.container {
text-align: center;
}
</style>
本文借鉴了一些大佬的文章,灵感更多的是自己项目经验的总结,若有问题还请大佬指出!
撒花完结。。。。。。。
推荐阅读
-
基于axios二次封装网络请求
-
35、RxJava\Okhttp\Retrofit 网络请求框架基本封装(一)
-
Android Xutils3网络请求的封装详解及实例代码
-
Spring Boot + Vue 前后端分离开发之前端网络请求封装与配置
-
Android Xutils3网络请求的封装详解及实例代码
-
vue小白教程-5 网络应用——axios发送请求
-
Vue项目调用后端接口api管理以及axios封装请求
-
Android Retrofit2+rxjava2+Mvp基于okhttp3网络请求框架的使用 一 框架配置
-
Android 中Volley二次封装并实现网络请求缓存
-
Android 中Volley二次封装并实现网络请求缓存