likes
comments
collection
share

02-对于axios请求的处理(添加请求拦截器、响应拦截器以及token处理还有请求头设置)

作者站长头像
站长
· 阅读数 86

axios请求处理


我们在配置完基本环境之后通常需要去配置好axios请求,包含配置请求的基地址、请求拦截器、响应拦截器、处理token权限以及过期问题、配置对应的请求头等等,其他操作可以去参考axios官网: www.axios-js.com/zh-cn/docs/

在src目录下创建utils文件夹,里面用于存放通用的一些工具类函数,比如说axios请求的工具配置、校验函数(日期格式化),localStorage本地存储等相关操作(存取删)

一、导入axios并设置接口的基地址

import store from '@/store' // 导入仓库,我们会对仓库里的数据进行操作
import axios from 'axios'  // 导入axios对象,用于创建一个axios实例
import router from '@/router' // 导入全局路由对象,用于后面导航到具体页面
import { Message } from 'element-ui' // 导入element-ui里的message方法,用于提示
// 创建一个axios实例
const service = axios.create({
  // 设置请求接口的基地址
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})

上面的 process.env.VUE_APP_BASE_API 是环境变量文件里设置好的地址,三个环境变量文件在启动或者运行项目的时候只会执行一个,三个文件是项目的不同阶段启动项目的时候用:dev是开发阶段,production是产品上线阶段,stage是测试阶段?忘了

  • yarn dev 会执行.env.development这个文件
  • yarn build:prod 会执行.env.production这个文件
  • yarn build:stage 会执行 .env.staging这个文件 这里的 VUE_APP_BASE_API 是设置代理的,设置代理之后,找不到地址的话就默认找自己的本地地址,找到本地地址访问之后,再通过proxy设置的代理地址,去访问真正的接口地址,解决跨域问题。 下面的两种书写方式是等价的,因为没写 http://localhost:9090 只写 api 的话,会自动补全,也就跟 http://localhost:9090/api 性质一样。port是设置端口号。

02-对于axios请求的处理(添加请求拦截器、响应拦截器以及token处理还有请求头设置) 在vue.config.js 文件中配置proxy代理服务器的节点

02-对于axios请求的处理(添加请求拦截器、响应拦截器以及token处理还有请求头设置)

举例:封装单独的登录接口

  • 基本封装 /api/user.js 中封装请求
import request from '@/utils/request'

export function reqLogin(data) {
  return request({
    method: 'post',
    url: '/sys/login', // 这里的 /api 由于开发环境所有接口都要加, 通过baseUrl加
    data
  })
}
  • 基于环境变量配置基地址 utils/request.js 配置基础地址
import axios from 'axios'

// 创建了axios实例, 使用的是自己的配置项
const instance = axios.create({
  // 开发环境, 找 env.development, 找 VUE_APP_BASE_API 变量
  // 生产环境, 找 env.production,  找 VUE_APP_BASE_API 变量
  baseURL: process.env.VUE_APP_BASE_API, // 环境变量
  timeout: 5000 // request timeout
})

// 请求拦截器

// 响应拦截器

export default instance
  • .env.development yarn dev 加载
# base api
# 最终请求地址 /api/sys/login => http://ihrm-java.itheima.net/api/sys/login
VUE_APP_BASE_API = '/api'
  • .env.production yarn build:prod 加载
# base api
# 最终请求地址: http://ihrm-java.itheima.net/api/sys/login
VUE_APP_BASE_API = 'http://ihrm-java.itheima.net/api/'
  • 页面测试:在页面中导入测试
import { reqLogin } from '@/api/user'

handleLogin() {
  this.$refs.loginForm.validate(async valid => {
      if (valid) {
          // 2.发送登录请求
          const res = await reqLogin(this.loginForm)
          console.log(res)
      }
  })
}

二、设置请求拦截器

因为我们在登录成功之后,服务器会返回一个叫token的身份令牌,我们需要用这个token令牌去访问对应的需要权限的网页,比如个人中心,或者其他私人展示的页面,或者其他需要令牌的地方。 进入这些网页通常是要发送请求的,然后就需要在每次发送请求之前都要在请求头中加入这个token字段,才可以被服务器识别并返回正确的数据。所以我们设置请求拦截器,在每次发送请求之前都携带这个令牌。

  • 下面的拦截器中,是从vuex的store里拿到预先存储好的token,并按照要求添加在了请求头中,这里是在token前面还拼接了一个Bearer字段。store里面的token是从本地localStorage里面取出来的,本地存储的token参数是在登录成功的时候后台返回给我们,我们在那个时候存进去。存进去的是一个对象tokenInfo,里面有一个token,一个retoken。我们拿这个token进行操作,token的时效一般是2小时,2小时之后token会过期,访问会退出,当我们检测到是因为token过期的原因导致请求失败的话,那么我们就要使用retoken重新向后台发送数据,拿到一个拥有新时效的token,继续拥有2小时时效,再继续发送请求并返回到刚才的页面。这个retoken也有时效,但是持续时间长一点,大概能有一周左右。
// 添加请求拦截器
service.interceptors.request.use(function(config) {
  // 在发送请求之前做些什么
  // 拿到token,添加到请求头中
  const token = store.getters.token
  if (token) config.headers.Authorization = `Bearer ${token}`
  return config
}, function(error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})

三、设置响应拦截器

下面的响应拦截器,首先是帮助初步判断是否请求成功,并且进行相关提示。请求成功之后根据返回值进行相关的操作,并且可以对响应数据进行初步结构,比如从response里结构出data,剥离一层,或者两层,return出去,那我们拿到的数据就简化了很多,省的后面反复结构取值。 响应错误的处理:响应错误会有很多种,我们这里是做了一个对token是否过期的判断,如果返回的状态码status===401并且data.code===10002,那就是说token过期了,这个规则是后端接口规定的。token过期了的一种处理就是拿着retoken向后台请求拿到新的token并存进本地,再重新请求返回刚才的页面。这里的处理是发现token过期了,手动清除掉本地存储的token值,并通过路由跳转到login登录页面进行重新登录,重新拿token值。

// 添加响应拦截器
service.interceptors.response.use(function(response) {
  // 对响应数据做点什么
  const { message, success } = response.data
  if (success) {
    Message.success(message)
  } else {
    Message.error(message)
    return Promise.reject(new Error(message))
  }
  return response
}, function(error) {
  console.dir(error)
  // 对响应错误做点什么
  // 如果响应的状态码是401,并且response.data.code是10002 说明token过期了, 让用户重新登录
  if (error.response.status === 401 && error.response.data.code === 10002) {
    // 1. 清除个人信息和token  触发logout的action
    store.dispatch('user/logout')
    // 2. 跳转到首页
    router.push('/login')
    // 3. 提示用户
    Message.error('登录超时正在退出...')
  } else {
    Message.error('服务器异常')
  }
  return Promise.reject(error)
})

四、导出处理过的service方法,其他地方要用就直接导入,导入的名字自己定义就行,本质上还是这个处理过的service

export default service
转载自:https://juejin.cn/post/7070847898832863269
评论
请登录