赞
踩
基于 Promise 网络请求库
特性
npm i -S axios qs
src/api/http.js:
- import Vue from 'vue';
- import axios from 'axios';
- import qs from 'qs';
- import router from '../router/index';
-
- let loadingService = null,
- loadingRequestQueue = [];
- // 默认接口配置
- let initConfig = {
- isNeedLoading: true, // 是否需要loading
- isHideErrorAlert: false, // 是否不显示错误弹窗
- };
-
- const instance = axios.create({
- timeout: 40000,
- });
- // post默认请求头设置
- instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
-
- // 请求拦截
- instance.interceptors.request.use(
- config => {
- // console.log('request--->', config);
-
- const { method = 'get' } = config;
- // config.headers.TrackId = config.trackId;
- // config.headers.CompanyId = 1693;
- if (method === 'post') {
- if (!config.data) {
- config.data = {};
- }
- if (config.submitType === 'json') {
- config.headers['Content-Type'] = 'application/json';
- // config.data = JSON.stringify(config.data) // axios内部自动会序列化
- } else {
- config.data = qs.stringify(config.data);
- }
- }
-
- return config;
- },
- error => {
- console.log('request error--->', error);
- return Promise.reject(error);
- }
- );
-
- // 响应拦截器
- instance.interceptors.response.use(
- response => {
- // console.log('response--->', response);
- if (response.status === 200) {
- return Promise.resolve(response);
- }
- return Promise.reject(response);
- },
- error => {
- // console.log('errorRes---->', error.response);
- // console.log('errorMsg---->', error.message);
-
- const Alert = Vue.prototype.$alert;
- const { response, message = '' } = error;
-
- // 在这里可以做个收集错误日志操作
-
- if (response && !response.config?.isHideErrorAlert) {
- if (message.indexOf('timeout') > -1) {
- Alert('请求超时请重试', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- }
- if (message.indexOf('Network Error') > -1) {
- Alert('网络出错', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- }
-
- switch (response.status) {
- case 400:
- Alert('400 请求参数有误', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
-
- // 401: 未登录
- // 未登录则跳转登录页面,并携带当前页面的路径
- // 在登录成功后返回当前页面,这一步需要在登录页操作。
- case 401:
- Alert({
- message: '未登录! ',
- type: 'warning',
- });
- router.replace({
- path: '/login',
- query: {
- redirect: router.currentRoute.fullPath,
- },
- });
- break;
-
- // 403 登录过期
- // 登录过期对用户进行提示
- // 清除本地token和清空vuex中token对象
- // 跳转登录页面
- case 403:
- Alert({
- message: '登录过期,请重新登录',
- type: 'warning',
- });
- setTimeout(() => {
- router.replace({
- path: '/login',
- query: {
- redirect: router.currentRoute.fullPath,
- },
- });
- }, 1000);
- break;
- case 404:
- Alert(response.config?.url + ' 404 Not Found', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
- case 405:
- Alert(response.config?.url + ' 405 请求未被允许', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
- case 500:
- Alert('500 服务器异常', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
- case 501:
- Alert('501 服务器不支持当前请求', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
- case 502:
- Alert('502 网关出错', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
- case 503:
- Alert('503 服务不可用', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
- case 504:
- Alert('504 网关超时', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
- default:
- Alert('网络出错', '异常信息', {
- confirmButtonText: '确定',
- type: 'error',
- });
- break;
- }
- }
-
- return Promise.reject(error);
- }
- );
-
- /**
- * 判断是否有接口还未加载完
- * @param {*} trackId
- */
- function compareLoadingStatus(trackId) {
- const targetIndex = loadingRequestQueue.findIndex(item => item === trackId);
- if (targetIndex > -1) {
- loadingRequestQueue.splice(targetIndex, 1);
- }
- if (!loadingRequestQueue.length) {
- loadingService?.close();
- }
- }
-
- function getTrackId() {
- return `trackid${new Date().getTime()}_${(Math.random() * 100000).toFixed(0)}`;
- }
-
- // 请求公共函数
- function send(method = 'get', url, data = {}, options = {}) {
- const Loading = Vue.prototype.$loading;
- options = {
- ...initConfig,
- ...options,
- trackId: getTrackId(),
- };
-
- if (options.isNeedLoading) {
- loadingRequestQueue.push(options.trackId);
- if (!loadingService) {
- loadingService = Loading?.({
- fullscreen: true,
- background: 'transparent',
- });
- }
- }
-
- return new Promise((resolve, reject) => {
- instance({
- method,
- url,
- [method === 'get' ? 'params' : 'data']: data,
- ...options,
- })
- .then(res => {
- resolve(res.data);
- })
- .catch(error => {
- reject(error);
- })
- .finally(() => {
- if (options.isNeedLoading) {
- compareLoadingStatus(options.trackId);
- }
- });
- });
- }
-
- /**
- * 封装get请求
- */
- export function get(url, params = {}, options = {}) {
- return send('get', url, params, options);
- }
-
- /**
- * 封装post请求
- */
- export function post(url, data = {}, options = {}) {
- return send('post', url, data, options);
- }

Loading 和 Alert 用的是 element-ui 的。
options 可选参数:
特有功能:
请求 headers 里的 Content-Type 可以不用设置,axios 会根据传入的 data 参数的格式自动设置 Content-Type:
data参数格式 | Content-Type |
---|---|
"name=jim&age=22" 这种序列化过的格式 | application/x-www-form-urlencoded |
普通对象 | application/json |
api接口管理的一个好处就是,我们把api统一集中起来,如果后期需要修改接口,我们就直接在api.js中找到对应的修改就好了,而不用去每一个页面查找我们的接口然后再修改会很麻烦。关键是,万一修改的量比较大,就gg了。还有就是如果直接在我们的业务代码修改接口,一不小心还容易动到我们的业务代码造成不必要的麻烦。
- // api.js
- import { get, post } from './http'
-
- export const apiAddress = parmas => post('api/v1/users/info', parmas);
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。