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中substr,substring,slice.splice的区别说明
Nov 25 Javascript
iphone safari不支持position fixed的解决方法
May 04 Javascript
js字符串截取函数substr substring slice使用对比
Nov 27 Javascript
浅谈javascript获取元素transform参数
Jul 24 Javascript
javascript实现二级级联菜单的简单制作
Nov 19 Javascript
利用JS判断鼠标移入元素的方向
Dec 11 Javascript
vue better-scroll插件使用详解
Jan 25 Javascript
node基于puppeteer模拟登录抓取页面的实现
May 09 Javascript
vue.js实现数据库的JSON数据输出渲染到html页面功能示例
Aug 03 Javascript
JS eval代码快速解密实例解析
Apr 23 Javascript
解决VantUI popup 弹窗不弹出或无蒙层的问题
Nov 03 Javascript
SSM VUE Axios详解
Oct 05 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
php foreach 参数强制类型转换的问题
2010/12/10 PHP
深入解析PHP的Yii框架中的event事件机制
2016/03/17 PHP
深入解析PHP的Yii框架中的缓存功能
2016/03/29 PHP
PHP让网站移动访问更加友好方法
2019/02/14 PHP
PHP变量的作用范围实例讲解
2020/12/22 PHP
JS获取整个页面文档的实现代码
2011/12/15 Javascript
JS图片预加载 JS实现图片预加载应用
2012/12/03 Javascript
javascript使用call调用微信API
2014/12/15 Javascript
JavaScript实现MIPS乘法模拟的方法
2015/04/17 Javascript
js获取页面description的方法
2015/05/21 Javascript
javascript检查浏览器是否已经启用XX功能
2015/07/10 Javascript
详解参数传递四种形式
2015/07/21 Javascript
nodejs创建web服务器之hello world程序
2015/08/20 NodeJs
AngularJS入门教程之服务(Service)
2016/07/27 Javascript
很棒的js Tab选项卡切换效果
2016/08/30 Javascript
easyui messager alert 三秒后自动关闭提示的实例
2016/11/07 Javascript
BootStrap树状图显示功能
2016/11/24 Javascript
JS拉起或下载app的实现代码
2017/02/22 Javascript
js实现适配不同的屏幕大小
2017/04/10 Javascript
vue给组件传递不同的值方法
2018/09/29 Javascript
使用kbone解决Vue项目同时支持小程序问题
2019/11/08 Javascript
学习python之编写简单乘法口诀表实现代码
2016/02/27 Python
深入学习python的yield和generator
2016/03/10 Python
python中不能连接超时的问题及解决方法
2018/06/10 Python
对Python3 序列解包详解
2019/02/16 Python
Django model select的多种用法详解
2019/07/16 Python
python如何将两个txt文件内容合并
2019/10/18 Python
深入解析HTML5使用SVG图像时的viewBox属性用法
2015/09/02 HTML / CSS
美国领先的家庭智能音响系统品牌:Sonos
2018/07/20 全球购物
前处理组长岗位职责
2014/03/01 职场文书
《庐山的云雾》教学反思
2014/04/22 职场文书
企业理念标语
2014/06/09 职场文书
小学一年级学生评语大全
2014/12/25 职场文书
2019银行竞聘书
2019/06/21 职场文书
Unicode中的CJK(中日韩统一表意文字)字符小结
2021/12/06 HTML / CSS
Android开发 使用文件储存的方式保存QQ密码
2022/04/24 Java/Android