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 相关文章推荐
漂亮的widgets,支持换肤和后期开发新皮肤(2007-4-27已更新1.7alpha)
Apr 27 Javascript
javascript读写XML实现广告轮换(兼容IE、FF)
Aug 09 Javascript
jQuery支持动态参数将函数绑定到事件上的方法
Mar 17 Javascript
jQuery实现商品活动倒计时
Oct 16 Javascript
jQuery Validate表单验证插件 添加class属性形式的校验
Jan 18 Javascript
基于Bootstrap的Metronic框架实现条码和二维码的生成及打印处理操作
Aug 29 Javascript
jquery 实现复选框的全选操作实例代码
Jan 24 Javascript
Angular4学习之Angular CLI的安装与使用教程
Jan 04 Javascript
vuejs 切换导航条高亮(路由菜单高亮)的方法示例
May 29 Javascript
解决eclipse中没有js代码提示的问题
Oct 10 Javascript
详解vue 不同环境配置不同的打包命令
Apr 07 Javascript
原生js实现表格循环滚动
Nov 24 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
新52大事件
2020/03/03 欧美动漫
PHP 常见郁闷问题答解
2006/11/25 PHP
php对mongodb的扩展(初出茅庐)
2012/11/11 PHP
深入Nginx + PHP 缓存详解
2013/07/11 PHP
PHP使用DOM和simplexml读取xml文档的方法示例
2017/02/08 PHP
Yii2中hasOne、hasMany及多对多关联查询的用法详解
2017/02/15 PHP
php使用PDO事务配合表格读取大量数据插入操作实现方法
2017/02/16 PHP
PHP的cookie与session原理及用法详解
2019/09/27 PHP
ext 代码生成器
2009/08/07 Javascript
javascript 操作cookies及正确使用cookies的属性
2009/10/15 Javascript
关于javascript中的typeof和instanceof介绍
2012/12/04 Javascript
jQuery实现加入购物车飞入动画效果
2015/03/14 Javascript
javascript中获取class的简单实现
2016/07/12 Javascript
微信小程序 WXML、WXSS 和JS介绍及详解
2016/10/08 Javascript
基于JS实现翻书效果的页面切换样式
2017/02/16 Javascript
前端把html表格生成为excel表格的实例
2017/09/19 Javascript
vue构建动态表单的方法示例
2018/09/22 Javascript
Python脚本实现格式化css文件
2015/04/08 Python
tornado 多进程模式解析
2018/01/15 Python
NumPy 数学函数及代数运算的实现代码
2018/07/18 Python
对python 匹配字符串开头和结尾的方法详解
2018/10/27 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
python argparser的具体使用
2019/11/10 Python
python3定位并识别图片验证码实现自动登录功能
2021/01/29 Python
CSS书写规范、顺序和命名规则
2014/03/06 HTML / CSS
美国领先的家庭健康检测试剂盒提供商:LetsGetChecked
2019/03/18 全球购物
将时尚融入珠宝:Adornmonde
2019/10/17 全球购物
小区停车场管理制度
2014/01/27 职场文书
会计专业自荐书
2014/07/08 职场文书
党员群众路线整改措施及今后努力方向
2014/10/28 职场文书
党的群众路线教育实践活动心得体会(医院)
2014/11/03 职场文书
学校勤俭节约倡议书
2015/04/29 职场文书
Nginx优化服务之网页压缩的实现方法
2021/03/31 Servers
SQLServer中exists和except用法介绍
2021/12/04 SQL Server
MySQ InnoDB和MyISAM存储引擎介绍
2022/04/26 MySQL
python 学习GCN图卷积神经网络
2022/05/11 Python