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 相关文章推荐
深入解析contentWindow, contentDocument
Jul 04 Javascript
JavaScript获取FCK编辑器信息的具体方法
Jul 12 Javascript
浅析JavaScript中的隐式类型转换
Dec 05 Javascript
javascript学习笔记整理(概述、变量、数据类型简介)
Oct 25 Javascript
jQuery-mobile事件监听与用法详解
Nov 23 Javascript
JS实现图片预览的两种方式
Jun 27 Javascript
基于Vue2的独立构建与运行时构建的差别(详解)
Dec 06 Javascript
vue slot 在子组件中显示父组件传递的模板
Mar 02 Javascript
vuejs实现标签选项卡动态更改css样式的方法
May 31 Javascript
javascript数据结构之多叉树经典操作示例【创建、添加、遍历、移除等】
Aug 01 Javascript
使用Phantomjs和Node完成网页的截屏快照的方法
Jul 16 Javascript
Element Notification通知的实现示例
Jul 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
简单谈谈php延迟静态绑定
2016/01/26 PHP
PHP使用finfo_file()函数检测上传图片类型的实现方法
2017/04/18 PHP
PHP进阶学习之反射基本概念与用法分析
2019/06/18 PHP
基于thinkphp6.0的success、error实现方法
2019/11/05 PHP
thinkphp5.1 框架导入/导出excel文件操作示例
2020/05/25 PHP
用于自动添加Digg This!按钮的JavaScript
2006/12/23 Javascript
js实现拖拽 闭包函数详细介绍
2012/11/25 Javascript
javascript简单事件处理和with用法介绍
2013/09/16 Javascript
JS中Eval解析JSON字符串的一个小问题
2016/02/21 Javascript
Bootstarp基本模版学习教程
2017/02/01 Javascript
Linux使用Node.js建立访问静态网页的服务实例详解
2017/03/21 Javascript
JS实现select选中option触发事件操作示例
2018/07/13 Javascript
关于node-bindings无法在Electron中使用的解决办法
2018/12/18 Javascript
详解JavaScript原生封装ajax请求和Jquery中的ajax请求
2019/02/14 jQuery
详解小程序循环require之坑
2019/03/08 Javascript
小程序异步问题之多个网络请求依次执行并依次收集请求结果
2019/05/05 Javascript
Vue实现返回顶部按钮实例代码
2020/10/21 Javascript
Python上传package到Pypi(代码简单)
2016/02/06 Python
Python制作Windows系统服务
2017/03/25 Python
Python实现输入二叉树的先序和中序遍历,再输出后序遍历操作示例
2018/07/27 Python
python3中os.path模块下常用的用法总结【推荐】
2018/09/16 Python
python3 字符串/列表/元组(str/list/tuple)相互转换方法及join()函数的使用
2019/04/03 Python
python制作朋友圈九宫格图片
2019/11/03 Python
Python 批量读取文件中指定字符的实现
2020/03/06 Python
基于Python下载网络图片方法汇总代码实例
2020/06/24 Python
Python turtle库的画笔控制说明
2020/06/28 Python
用于ETL的Python数据转换工具详解
2020/07/21 Python
html5 sessionStorage会话存储_动力节点Java学院整理
2017/07/06 HTML / CSS
应聘教师自荐信
2013/10/12 职场文书
学生打架检讨书1000字
2014/01/16 职场文书
安全教育感言
2014/03/04 职场文书
教师读书活动总结
2014/05/07 职场文书
城管个人总结
2015/02/28 职场文书
2015年乡镇纪委工作总结
2015/05/26 职场文书
小学四年级作文之写景
2019/08/23 职场文书
idea编译器vue缩进报错问题场景分析
2021/07/04 Vue.js