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 相关文章推荐
零基础学JavaScript最新动画教程+iso光盘下载
Jan 22 Javascript
javascript 支持ie和firefox杰奇翻页函数
Jul 22 Javascript
使用 JScript 创建 .exe 或 .dll 文件的方法
Jul 13 Javascript
js控制元素显示在屏幕固定位置及监听屏幕高度变化的方法
Aug 11 Javascript
javascript伸缩菜单栏实现代码分享
Nov 12 Javascript
快速学习jQuery插件 jquery.validate.js表单验证插件使用方法
Dec 01 Javascript
Jquery zTree 树控件异步加载操作
Feb 25 Javascript
Angular页面间切换及传值的4种方法
Nov 04 Javascript
Bootstrap媒体对象学习使用
Mar 07 Javascript
bootstrap select插件封装成Vue2.0组件
Apr 17 Javascript
JavaScript计算正方形面积
Nov 26 Javascript
Vue为什么要谨慎使用$attrs与$listeners
Aug 27 Javascript
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
Zend Framework中的简单工厂模式 图文
2012/07/10 PHP
Yii2中如何使用modal弹窗(基本使用)
2016/05/30 PHP
JQuery 绑定select标签的onchange事件,弹出选择的值,并实现跳转、传参
2011/01/06 Javascript
Javascript模块化编程(三)require.js的用法及功能介绍
2013/01/17 Javascript
javascript实现TreeView 无刷新展开的实例代码
2013/07/13 Javascript
js实现浏览本地文件并显示扩展名的方法
2015/08/17 Javascript
jQuery实现图片向左向右切换效果的简单实例
2016/05/18 Javascript
javascript使用 concat 方法对数组进行合并的方法
2016/09/08 Javascript
详解Vue中localstorage和sessionstorage的使用
2017/12/22 Javascript
JavaScript判断日期时间差的实例代码
2018/03/01 Javascript
JavaScript实现的简单Tab点击切换功能示例
2018/07/06 Javascript
vue中Element-ui 输入银行账号每四位加一个空格的实现代码
2018/09/14 Javascript
javascript实现遮罩层动态效果实例
2019/05/14 Javascript
使用layui的layer组件做弹出层的例子
2019/09/27 Javascript
通过原生vue添加滚动加载更多功能
2019/11/21 Javascript
vue从零实现一个消息通知组件的方法详解
2020/03/16 Javascript
基于JavaScript实现控制下拉列表
2020/05/08 Javascript
Vue 中使用lodash对事件进行防抖和节流操作
2020/07/26 Javascript
原生JS实现弹幕效果的简单操作指南
2020/11/10 Javascript
Python类方法__init__和__del__构造、析构过程分析
2015/03/06 Python
浅谈python中scipy.misc.logsumexp函数的运用场景
2016/06/23 Python
Python多进程multiprocessing用法实例分析
2017/08/18 Python
使用anaconda的pip安装第三方python包的操作步骤
2018/06/11 Python
Python 串口读写的实现方法
2019/06/12 Python
python中的global关键字的使用方法
2019/08/20 Python
python中的数组赋值与拷贝的区别详解
2019/11/26 Python
python利用opencv保存、播放视频
2020/11/02 Python
HTML5: Web 标准最巨大的飞跃
2008/10/17 HTML / CSS
HTML5视频支持检测(检查浏览器是否支持视频播放)
2013/06/08 HTML / CSS
365 Tickets英国:全球景点门票
2019/07/06 全球购物
应届优秀本科大学毕业生自我鉴定
2014/01/21 职场文书
表彰会主持词
2014/03/26 职场文书
四风问题个人剖析材料
2014/10/07 职场文书
世界环境日活动总结
2015/02/11 职场文书
国家助学贷款承诺书
2015/04/30 职场文书
InterProcessMutex实现zookeeper分布式锁原理
2022/03/21 Java/Android