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变强势
Jun 22 Javascript
js创建数据共享接口——简化框架之间相互传值
Oct 23 Javascript
treepanel动态加载数据实现代码
Dec 15 Javascript
浅谈JavaScript Array对象
Dec 29 Javascript
jQuery子属性过滤选择器用法分析
Feb 10 Javascript
如何使用jquery easyui创建标签组件
Nov 18 Javascript
Bootstrap每天必学之轮播(Carousel)插件
Apr 25 Javascript
JS简单实现自定义右键菜单实例
May 31 Javascript
Node.js dgram模块实现UDP通信示例代码
Sep 26 Javascript
vue.js在标签属性中插入变量参数的方法
Mar 06 Javascript
解决layui上传文件提示上传异常,实际文件已经上传成功的问题
Aug 19 Javascript
解决vue项目刷新后,导航菜单高亮显示的位置不对问题
Nov 01 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
PHP调用JAVA的WebService简单实例
2014/03/11 PHP
PHP中把对象数组转换成普通数组的方法
2015/07/10 PHP
Windows Server 2008 R2和2012中PHP连接MySQL过慢的解决方法
2016/07/02 PHP
PHP实现活动人选抽奖功能
2017/04/19 PHP
PHP数组式访问接口ArrayAccess用法分析
2017/12/28 PHP
php记录搜索引擎爬行记录的实现代码
2018/03/02 PHP
javascript 字符串连接的性能问题(多浏览器)
2008/11/18 Javascript
基于jquery 的一个progressbar widge
2010/10/29 Javascript
js螺旋动画效果的具体实例
2013/11/15 Javascript
jquery easyui combobox模糊过滤(示例代码)
2013/11/30 Javascript
Bootstrap每天必学之标签页(Tab)插件
2020/08/09 Javascript
如何实现json数据可视化详解
2016/11/24 Javascript
JQuery validate 验证一个单独的表单元素实例
2017/02/17 Javascript
jQuery实现select下拉框获取当前选中文本、值、索引
2017/05/08 jQuery
layui实现form表单同时提交数据和文件的代码
2019/10/25 Javascript
微信小程序仿抖音短视频切换效果的实例代码
2020/06/24 Javascript
[05:15]2018年度CS GO社区贡献奖-完美盛典
2018/12/16 DOTA
Python用于学习重要算法的模块pygorithm实例浅析
2018/08/16 Python
在Python 中同一个类两个函数间变量的调用方法
2019/01/31 Python
详解Python匿名函数(lambda函数)
2019/04/19 Python
解决python-docx打包之后找不到default.docx的问题
2020/02/13 Python
Python可视化工具如何实现动态图表
2020/10/23 Python
HTML5在a标签内放置块级元素示例代码
2013/08/23 HTML / CSS
荷兰度假屋租赁网站:Aan Zee
2020/02/28 全球购物
zooplus德国:便宜地订购动物用品、动物饲料、动物食品
2020/05/06 全球购物
大学生求职推荐信
2013/11/27 职场文书
无工作经验者个人求职信范文
2013/12/22 职场文书
三方协议书范本
2014/04/22 职场文书
党员创先争优活动总结
2014/05/04 职场文书
普通党员个人剖析材料
2014/10/08 职场文书
2014年驻村干部工作总结
2014/11/17 职场文书
2014年保管员工作总结
2014/11/18 职场文书
出国留学英文自荐信
2015/03/25 职场文书
公司人力资源管理制度
2015/08/05 职场文书
医院岗前培训心得体会
2016/01/08 职场文书
Python线程池与GIL全局锁实现抽奖小案例
2022/04/13 Python