VUE Axios取消请求 - CancelToken

铺垫

  Axios 是一个基于 Promise 的 HTTP 库,它的浏览器支持性良好,是Vue主推请求异步的方法;它支持多种请求的简写和请求参数的配置,也支持使用自定义配置新建一个axios实例,举例如下

const request = axios.create({
  baseURL: 'https://domain-name.com/api/'
  timeout: 8000
})

  其中,create()方法中是自定义的初始化配置参数。初始化数据除此之外,通常还会设置拦截器,实现header参数添加,错误打印及HTTP码的统一处理等,如下

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    if (store.getters.token) {
      config.headers.common['X-Token'] = getToken()
      config.headers.common['X-Requested-With'] = 'XMLHttpRequest'
      config.headers.common['Access-Control-Allow-Origin'] = '*'
      config.params = {
        _t: Date.parse(new Date()) / 1000,
        ...config.params
      }
    return config;
  }, function (error) {
    console.log('request error:', error)
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    if (res.code !== 0) {
      console.log(`请求错误: ${res.request.responseURL} \nCode: ${res.data.code}`);
    }
    return response;
  }, function (error) { // request timeout is an error
    let msg = 'UnknownError'
    const res = error.response
    if (res) {
      msg = errorMessage.find((t) => t.code === res.status).msg || msg
      if (res.status === 401 || res.status === 403) {
        window.location.href = res.data.redirect_url
      } else {
        Message.error(msg)
      }
    } else {
      Message.error(error.message)
    }
    return Promise.reject(error);
  });
// HTTP CODE及错误提示
const errorMessage = [
  { code: 400, msg: '请求错误' },
  { code: 401, msg: '未授权,请登录' },
  { code: 403, msg: '拒绝访问' },
  { code: 404, msg: '请求地址出错' },
  { code: 408, msg: '请求超时' },
  { code: 500, msg: '服务器内部错误' },
  { code: 501, msg: '服务未实现' },
  { code: 502, msg: '网关错误' },
  { code: 503, msg: '服务不可用' },
  { code: 504, msg: '网关超时' },
  { code: 505, msg: 'HTTP版本不受支持' }
]

  一般我们将它封装为request.js文件并暴露出接口以便外部使用。在外部调用的过程中,如遇到不符合要求或需要新增的config参数是允许覆盖和新增的,编写如下

import request from '@/request'

export function queryUserInfo(data) {
  return request({
    url: '/users/userInfo',
    method: 'get',
    params: data
  })
}

  这里,request方法中的配置参数会按一定的规则merge到最终的Axios请求中。

 取消重复的请求

先来回顾一下官网讲解的内容

Axios使用cancel token取消请求,它基于cancelable promises proposal实现,目前该API还处在第一阶段

  官网介绍了取消请求的两种办法:

1. 可以利用CancelToken工厂函数创建cancel token

const CancelToken = axios.CancelToken;
const source = CancelToken.source();
// get 方法使用案例
axios.get('user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message)
  } else {
    // TODO: handle error
  }
})
// post 使用案例
axios.post('/user/12345', {
  name: 'name what'
}, {
  cancelToken: source.token
})

// 执行取消请求操作
source.cancel(‘请求已取消’)

2. 传递executor函数到CancelToken的够造函数来创建cancel token

const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    cancel = c
  })
})

// 执行取消请求操作
cancel()

  并且官网特意强调了,不同请求可以定义同一个取消请求的方法名,来批量取消多个请求。

案例

  结合【铺垫】内容,笔者使用方法2来举例实现取消请求,还是拿上方的请求为例,做如下修改

import request from '@/utils/request'
import axios from 'axios'

export function queryUserInfo(data, _this) {
  const CancelToken= axios.CancelToken
  return request({
    url: '/users/userInfo',
    method: 'get',
    params: data,
    cancelToken: new CancelToken(function executor(c) {
      _this.cancelAjax = c
    })
  })
}

  以上我们利用executor生成了取消函数,并赋值给外部真实请求传入的环境中,形参_this的实参为Vue的this变量。

// 选择人员列表查询
getUserInfo() {
  if (typeof this.cancelAjax === 'function') {
    this.cancelAjax()
  }
  this.allUsers.loading = true
  queryUserInfo({ userId: '20192430139' }, this).then(res => {
    if (res.code === 1) {
      this.userInfo.data = res.data
      this.allUsers.loading = false
    } else {
      this.$message.error(res.msg || 'get userInfo error')
    }
  })
}

  思路就是,当请求发起时cancelToken会派发函数给data中的cancelAjax,可以利用数据类型侦查是否请求正在发生。cancelAjax在页面初始化时定义为null即可

<template>

</template>
<script>
export default {
  data() {
    return {
      cancelAjax: null
    }
  }
}
</script>

猜你喜欢

转载自blog.csdn.net/ka_xingl/article/details/120132135