vue axios基于常见业务场景的二次封装的实现


Posted in Javascript onSeptember 21, 2018

axios

axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

在前端框架中的应用也是特别广泛,不管是vue还是react,都有很多项目用axios作为网络请求库。

我在最近的几个项目中都有使用axios,并基于axios根据常见的业务场景封装了一个通用的request服务。

npm:

$ npm install axios

bower:

$ bower install axios

Using cdn:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

业务场景:

  1. 全局请求配置。
  2. get,post,put,delete等请求的promise封装。
  3. 全局请求状态管理,供加载动画等使用。
  4. 路由跳转取消当前页面请求。
  5. 请求携带token,权限错误统一管理。

默认配置

定义全局的默认配置

axios.defaults.timeout = 10000 //超时取消请求
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
axios.defaults.baseURL = process.env.BASE_URL

自定义配置(非常见业务场景,仅作介绍)

// 创建实例时设置配置的默认值
var instance = axios.create({
 baseURL: 'https://api.another.com'
});
// 在实例已创建后修改默认值
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;

优先级:自定义配置 > 默认配置

请求及响应拦截器

请求拦截器

// 请求列表
const requestList = []
axios.interceptors.request.use((config) => {
 //1.将当前请求的URL添加进请求列表数组
 requestList.push(config.url)
 //2.请求开始,改变loading状态供加载动画使用
 store.dispatch('changeGlobalState', {loading: true})
 //3.从store中获取token并添加到请求头供后端作权限校验
 const token = store.getters.userInfo.token
 if (token) {
  config.headers.token = token
 }
 return config
}, function (error) {
 return Promise.reject(error)
})

1.请求拦截器中将所有请求的url添加进请求列表变量,为取消请求及loading状态管理做准备
2.请求一旦开始,就可以开启动画加载效果。
3.用户登录后可以在请求头中携带token做权限校验使用。

响应拦截器

axios.interceptors.response.use(function (response) {
 // 1.将当前请求中请求列表中删除
 requestList.splice(requestList.findIndex(item => item === response.config.url), 1)
 // 2.当请求列表为空时,更改loading状态
 if (requestList.length === 0) {
  store.dispatch('changeGlobalState', {loading: false})
 }
 // 3.统一处理权限认证错误管理
 if (response.data.code === 900401) {
  window.ELEMENT.Message.error('认证失效,请重新登录!', 1000)
  router.push('/login')
 }
 return response
}, function (error) {
 // 4.处理取消请求
 if (axios.isCancel(error)) {
  requestList.length = 0
  store.dispatch('changeGlobalState', {loading: false})
  throw new axios.Cancel('cancel request')
 } else {
  // 5.处理网络请求失败
  window.ELEMENT.Message.error('网络请求失败', 1000)
 }
 return Promise.reject(error)
})

1.响应返回后将相应的请求从请求列表中删除
2.当请求列表为空时,即所有请求结束,加载动画结束
3.权限认证报错统一拦截处理
4.取消请求的处理需要结合其他代码说明
5.由于项目后端并没有采用RESTful风格的接口请求,200以外都归为网络请求失败

promise封装及取消请求

const CancelToken = axios.CancelToken
//cancel token列表
let sources = []
const request = function (url, params, config, method) {
 return new Promise((resolve, reject) => {
  axios[method](url, params, Object.assign({}, config, {
  //1.通过将执行程序函数传递给CancelToken构造函数来创建cancel token
   cancelToken: new CancelToken(function executor (c) {
   //2.将cancel token存入列表
    sources.push(c)
   })
  })).then(response => {
   resolve(response.data)
  }, err => {
   if (err.Cancel) {
    console.log(err)
   } else {
    reject(err)
   }
  }).catch(err => {
   reject(err)
  })
 })
}

const post = (url, params, config = {}) => {
 return request(url, params, config, 'post')
}

const get = (url, params, config = {}) => {
 return request(url, params, config, 'get')
}
//3.导出cancel token列表供全局路由守卫使用
export {sources, post, get}

1.axios cancel token API
2.存入需要取消的请求列表导出给导航守卫使用
3.router.js

...
import { sources } from '../service/request'
...
router.beforeEach((to, from, next) => {
 document.title = to.meta.title || to.name
  //路由发生变化时取消当前页面网络请求
 sources.forEach(item => {
  item()
 })
 sources.length = 0
 next()
})

request.js完整代码:

// 引入网络请求库 https://github.com/axios/axios

import axios from 'axios'
import store from '../store'
import router from '../router'

// axios.defaults.timeout = 10000
const requestList = []

axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'

axios.defaults.baseURL = process.env.BASE_URL
// 自定义拦截器
axios.interceptors.request.use((config) => {
 requestList.push(config.url)
 store.dispatch('changeGlobalState', {loading: true})
 const token = store.getters.userInfo.token
 if (token) {
  config.headers.token = token
 }
 return config
}, function (error) {
 return Promise.reject(error)
})

axios.interceptors.response.use(function (response) {
 requestList.splice(requestList.findIndex(item => item === response.config.url), 1)
 if (requestList.length === 0) {
  store.dispatch('changeGlobalState', {loading: false})
 }
 if (response.data.code === 900401) {
  window.$toast.error('认证失效,请重新登录!', 1000)
  router.push('/login')
 }
 return response
}, function (error) {
 requestList.length = 0
 store.dispatch('changeGlobalState', {loading: false})
 if (axios.isCancel(error)) {
  throw new axios.Cancel('cancel request')
 } else {
  window.$toast.error('网络请求失败!', 1000)
 }
 return Promise.reject(error)
})

const CancelToken = axios.CancelToken
let sources = []

const request = function (url, params, config, method) {
 return new Promise((resolve, reject) => {
  axios[method](url, params, Object.assign(config, {
   cancelToken: new CancelToken(function executor (c) {
    sources.push(c)
   })
  })).then(response => {
   resolve(response.data)
  }, err => {
   reject(err)
  }).catch(err => {
   reject(err)
  })
 })
}

const post = (url, params, config = {}) => {
 return request(url, params, config, 'post')
}

const get = (url, params, config = {}) => {
 return request(url, params, config, 'get')
}

export {sources, post, get}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery的一些特性和用法整理小结
Jan 13 Javascript
Jqyery中同等与js中windows.onload的应用
May 10 Javascript
html向js方法传递参数具体实现
Aug 08 Javascript
jQuery实现漂亮实用的商品图片tips提示框效果(无图片箭头+阴影)
Apr 16 Javascript
微信小程序 触控事件详细介绍
Oct 17 Javascript
Vue.js实现一个漂亮、灵活、可复用的提示组件示例
Mar 17 Javascript
vue 计时器组件的实现代码
Sep 14 Javascript
vue element-ui table表格滚动加载方法
Mar 02 Javascript
一步快速解决微信小程序中textarea层级太高遮挡其他组件
Mar 04 Javascript
javascript 内存模型实例详解
Apr 18 Javascript
JS绘图Flot应用图形绘制异常解决方案
Oct 16 Javascript
浅谈Vue开发人员的7个最好的VSCode扩展
Jan 20 Vue.js
vue2使用keep-alive缓存多层列表页的方法
Sep 21 #Javascript
使用ng-packagr打包Angular的方法示例
Sep 21 #Javascript
基于vue中keep-alive缓存问题的解决方法
Sep 21 #Javascript
vue中前进刷新、后退缓存用户浏览数据和浏览位置的实例讲解
Sep 21 #Javascript
vue单页面应用打开新窗口显示跳转页面的实例
Sep 21 #Javascript
详解Vue改变数组中对象的属性不重新渲染View的解决方案
Sep 21 #Javascript
默认浏览器设置及vue自动打开页面的方法
Sep 21 #Javascript
You might like
FCKeditor添加自定义按钮
2008/03/27 PHP
PHP执行批量mysql语句的解决方法
2013/05/02 PHP
PHP中使用CURL模拟登录并获取数据实例
2014/07/01 PHP
php接口技术实例详解
2016/12/07 PHP
php+redis消息队列实现抢购功能
2018/02/08 PHP
jQuery之选择组件的深入解析
2013/06/19 Javascript
jQuery实现类似滑动门切换效果的层切换
2013/09/23 Javascript
JavaScript 里的类数组对象
2015/04/08 Javascript
javascript中in运算符用法分析
2015/04/28 Javascript
Js实现无刷新删除内容
2015/04/29 Javascript
js数组如何添加json数据及js数组与json的区别
2015/10/27 Javascript
AngularJS ng-blur 指令详解及简单实例
2016/07/30 Javascript
NodeJS实现图片上传代码(Express)
2017/06/30 NodeJs
Angularjs自定义指令实现分页插件(DEMO)
2017/09/16 Javascript
微信小程序实现左滑动删除效果
2020/03/30 Javascript
Layui数据表格判断编辑输入的值,是否为我需要的类型详解
2019/10/26 Javascript
react基本安装与测试示例
2020/04/27 Javascript
基于canvasJS在PHP中制作动态图表
2020/05/30 Javascript
浅谈实现在线预览PDF的几种解决办法
2020/08/10 Javascript
python删除文件示例分享
2014/01/28 Python
Python类定义和类继承详解
2015/05/08 Python
使用Python脚本将文字转换为图片的实例分享
2015/08/29 Python
数据清洗--DataFrame中的空值处理方法
2018/07/03 Python
Python异常模块traceback用法实例分析
2019/10/22 Python
python range实例用法分享
2020/02/06 Python
python实现QQ邮箱发送邮件
2020/03/06 Python
详解Css3新特性应用之过渡与动画
2017/01/10 HTML / CSS
优秀员工自荐信范文
2013/10/05 职场文书
2014年元旦活动方案
2014/02/15 职场文书
人民教师求职自荐信
2014/03/12 职场文书
关于环保的演讲稿
2014/05/10 职场文书
信息与工商管理职业规划范文:为梦想而搏击
2014/09/11 职场文书
关于五一放假的通知
2015/08/18 职场文书
MySQL分库分表与分区的入门指南
2021/04/22 MySQL
Python使用OpenCV实现虚拟缩放效果
2022/02/28 Python
【海涛教你打DOTA】虚空假面第一视角骨弓3房29杀
2022/04/01 DOTA