axios(封装使用、拦截特定请求、判断所有请求加载完毕)

2019-12-16 15:15:50

参考地址 axios(封装使用、拦截特定请求、判断所有请求加载完毕)


  • 基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 Node.js 中使用

  • vue2.0之后,就不再对 vue-resource 更新,而是推荐使用 axios,本项目也是使用 axios

  • 功能特性

  1. 在浏览器中发送 XMLHttpRequests 请求

  2. 在 node.js 中发送 http请求

  3. 支持 Promise API

  4. 拦截请求和响应

  5. 转换请求和响应数据

  6. 取消请求

  7. 自动转换 JSON 数据

  8. 客户端支持保护安全免受 CSRF/XSRF(跨站请求伪造) 攻击

封装使用

建议拆分三个文件

  • src
    -> service
    ---->axios.js (axios 配置,拦截器、统一 url)
    ---->index.js (接口方法,里面调用 api 方法,供页面级调用)
    ---->api
    ------->index.js(api 方法,里面调用后端提供的接口,供接口方法调用)

axios.js 基本配置

'use strict';import axios from 'axios';// 自动识别接口使用开发环境地址(开发环境地址做了 proxyTable 代理,故设置为空)或线上地址axios.defaults.baseURL = process.env.NODE_ENV === 'production' ? process.env.API_ROOT : '';// 开发环境直接打包测试// axios.defaults.baseURL = '';axios.interceptors.request.use(config => {  return config;
}, error => {  console.log(error);  return Promise.reject(error);
});

axios.interceptors.response.use(res => {  const apiRes = res.data;  return apiRes;
}, async error => {  console.dir(error);  return Promise.reject(error);
});export default axios;


api/index.js 调用后端提供的接口

import Ax from '@/service/axios';import qs from 'qs';export default {
  fetchBlog (reqData) {    return Ax.get('/krryblog/blog/getBlog', {params: reqData});
  },
  addBlog (reqData) {    return Ax.post('/krryblog/blog/addBlog', qs.stringify(reqData));
  },
  updateBlog (reqData) {    return Ax.post('/krryblog/blog/updateBlog', qs.stringify(reqData));
  },
  deleteBlogCover (id, reqData) {    return Ax.post(`/krryblog/blog/deleteBlogCover/${id}`, qs.stringify(reqData));
  },
};


index.js 接口方法(调用 api)

import Api from './api';export async function getBlog(reqData) {  let res = await Api.fetchBlog(reqData);  return res;
},export async function addBlog (reqData) {  let res = await Api.addBlog(reqData);  return res;
},export async function updateBlog (reqData) {  let res = await Api.updateBlog(reqData);  return res;
},export async function deleteBlogCover (id, reqData) {  let res = await Api.deleteBlogCover(id, reqData);  return res;
},

页面调用

接下来就可以愉快地在页面调用了

import { getBlog } from '@/service'export default {
  data() {    return {      tableData: [],      pageIndex: 1,      pageSize: 9
    }
  },
  created() {    this.getList();
  },  methods: {    async getList() {      let { result } = await getBlog({        pageIndex: this.pageIndex,        pageSize: this.pageSize
      });    this.tableData = result.data;
  },
}

axios 执行多个并发请求

async getList() {  let resArr = []  for (let val of this.arrId) {    // push 请求
    resArr.push(queryPropertyValue({ id: val }))
  }  this.tableData = []  Promise.all(resArr).then(res => {    for (let val of res) {      let vals = val.result.propertyValues      // 每个请求的结果 push 到 tableData
      vals.forEach(item => this.tableData.push(item))
    }
  })
},

或者直接在 axios 写 promise all

// 根据 id 获取某一条商品数据let getDetail = (id)=>{  return axios.get(`/detail?bid=${id}`);
}// 检测登录的用户是否将此商品加入购物车let detectCar = (shopId,userId)=>{  return axios.get(`/detectCar?shopId=${shopId}&userId=${userId}`);
}// 获取一条商品数据、并且检测是否加入购物车let getDeAll = (shopId,userId)=>{
  axios.all([
    getDetail(shopId),
    detectCar(shopId,userId)
  ]).then(axios.spread((resDetail, resCar)=>{    // 两个请求现已完成
    // 打印两个请求的响应值  
    console.log(resDetail);    console.log(resCar);
  }));
}
  • 实例的方法

axios#request(config)
axios#get(url [,config])
axios#delete(url [,config])
axios#head(url [,config])
axios#post(url [,data [,config]])
axios#put(url [,data [,config]])
axios#patch(url [,data [,config]])
  • 请求配置:只有url是必需的,如果未指定方法,请求将默认为GET

axios 拦截特定请求

业务上经常出现这个问题,需要拦截某些特定请求,在该特定请求,页面采取或不采取什么变化

研究 axios 的 request 统一拦截方法:axios.interceptors.request.use(function (config) {})
参数 config 如下:
p_70.png

可以发现 config.url 就是请求的接口的地址,那么 “/” 最后的 getClassify 就是该请求的方法,就可以通过取出该字符串来判断某些特定请求,从而做出怎样的变化

axios.interceptors.request.use(config => {  // 判断请求是否是 getClassify,如果是 getClassify,不加载 LoadingBar
  let url = config.url;  if (url.split('/').pop() === 'getClassify') {
    flag = false;
  } else {
    iView.LoadingBar.start();
    flag = true;
  }  return config;
}, error => {  console.log(error);  return Promise.reject(error);
});

如何判断所有请求加载完毕

判断所有请求加载完毕,可以解决这个问题:在刚开始第一个请求,加载 loading 动画,所有请求加载完成后,关闭 loading 动画

let reqNum = 0axios.interceptors.request.use(config => {  // 在请求发出之前进行一些操作,每次发出请求就 reqNum++
  reqNum++
  _bus.$emit('showloading')  return config
}

axios.interceptors.response.use(response => {  // 接受请求后 reqNum--,判断请求所有请求是否完成
  reqNum--  if (reqNum <= 0) {
    _bus.$emit('closeLoading')
  } else {
    _bus.$emit('showloading')
  }
})

axios post 请求 相关问题

  • 如果遇到 post 请求跨域问题,在 webpack 配置文件可以设置 proxyTable 处理跨域问题

  • 传送门:https://ainyi.com/27

  • post 请求携带参数,需要做一次序列化:qs.stringify(reqData)

saveNormalAds (reqData) {  return Ax.post('/index.php?krry', qs.stringify(reqData));
},


  • 2019-06-04 16:40:30

    为了美观当网页图片不存在时不显示叉叉图片

    当在页面显示的时候,万一图片被移动了位置或者丢失的话,将会在页面显示一个带X的图片,很是影响用户的体验。即使使用alt属性给出了”图片XX”的提示信息,也起不了多大作用。

  • 2019-06-04 17:38:44

    PHP时间转换今天昨天前天几天前

    实际情况应该是,昨天任何时间都算一天前,前天任意时间都算2天前,所以自己琢磨了一番,去动态更新时间与今天23:59:59相差的时间秒数与86400(24 x 3600)相除后,向下取整,这样就得到了相差的天数,比如昨天00:00~昨天23:59:59的任何时间与今天的23:59:59,都相差 86400~(86400 x 2) 天,也就是2天。

  • 2019-06-04 17:44:14

    【VUE】图片预览放大缩小插件

    在看项目时,突然看到预览图片的弹窗,感觉好僵硬,不能放大,不能切换,于是便在网上找下关于图片预览的插件,有找到三个插件,具体的优劣势的看自己的使用吧,我目前只是在电脑查看效果,分别是viewerjs插件、基于photoswipe的vue-photo-preview插件以及vue-picture-preview插件 作者:北极星丶超帅的 链接:https://www.jianshu.com/p/e3350aa1b0d0 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 2019-06-04 21:32:05

    Android 全局Dialog的简单实现

    这里所说的全局Dialog是指无论当前应用是处于哪一个页面上,都能够及时弹出Dialog来提示用户一些信息,用户体验不会很好,一般应用于优先级非常高的通知。

  • 2019-06-06 16:14:50

    intent-filter的action,category,data匹配规则

    我们知道有两种方式来启动Activity,显示调用和隐式调用。当使用隐式调用时,又会涉及到IntentFilter的匹配规则。我确信大多数开发者很少关注隐式调用,因为平时开发中用到大多数是显示调用。例如:用Intent直接打开一个Activity,或者用Intent通过包名等其他信息打开另外一个应用等。而隐式调用则使用的比较少,当然也不是完全不使用。例如:当我们需要打开浏览器访问某个链接时,手机上可能存在多个浏览器,我们也无法拿到某一个浏览器的包名,那么一般情况下我们会写如下代码:

  • 2019-06-06 17:57:57

    input【type="checkbox"】标签与字体对齐

    今天分享一个比较实用的技巧,在实际项目中我们会经常遇到表单的input标签多选和单选的问题,但是往往由于标签自身的样式和我们项目的风格很不搭调,就不能实现了,今天就来告诉大家怎么去实现吧。

  • 2019-06-10 11:54:52

    html.div禁用点击事件

    今天做项目中偶然误把元素加上了pointer-events属性,结果导致后来在js中给该元素加点击事件不能用,检查了半天才发现是这个属性的问题。之前没有好好研究,于是决定仔细研究一下。