vue中对axios进行二次封装,如1:接口超时、2: 全局loading、3: header中增加token、4: 接口认证失败统一跳转登陆页面

3 篇文章 0 订阅
一、使用axios中的疑问?

1、如果使用封装好的axios,每个请求都会执行拦截器嘛?

会的,因为axios.interceptors.request.use执行了,但是保存在函数内部的reqObj只会执行一次。

疑问???axios.interceptors.request是如何执行的????

参考promise源码自己写的axios源码实现axios文件中:只要调用Axios.prototype.request中就会执行

(1)Axios.prototype.request = function(config) {
  let promise = Promise.resolve(config)
  let chains = [dispatchRequest, undefined]
  this.interceptors.request.forEach(function(interRequest) {
    chains.unshift( interRequest.resolved, interRequest.rejected )
  })
  while( chains.length ){
    promise = promise.then(chains.shift(), chains.shift())
  }
  return promise
}

function axiosGlobal() {
  let reqObj = {}
  return axios
}

Vue.prototype.$http = axiosGlobal()

this.$http.get('3000')
this.$http.get('4000')

2、axios添加全局的loading,是每个请求都会有自己的,还是统一所有的请求都使用一个?

是统一的loading,因为在 interceptors.request 中加载,reqObj为空打开loading,当自己的请求执行完将开关改为reqObj[key] = false // key = url + 时间戳
当然等所有的请求都执行完才会关闭loding,这样效果会比较好

二、axiosGlobal函数将如何封装,当然是用闭包,返回一个axios,内部的变量(reqObj)可以不被回收,因为axios.interceptors内部使用到这个变量

  例如:
  export function axiosGlobal() {
    let reqObj = {}
    axios.interceptors.request.use(config => {
      if (!reqObj[key]) { // key = url + 时间戳
        loading.show()
      }
    }
    return axios
  }

三、PSMU 绑定在window中的变量 尽量保持业务无关

可以在 axiosGlobal 中做封装什么

1、接口超时(特定接口不能保证请求时长的,可以排除在外)
2、封装全局 loading
3、请求头 headers 中增加所需要的key: value

3.1、请求唯一id(zing-id),方便后端查看日志
3.2、请求发送时间
3.3、是否有token,存在:增加到headers[‘Authorization’] = get.token()

4、在 响应拦截器 中统一跳转登陆页面,怎么操作的??

1、只有一个接口 code = 299,认证失败,直接跳转登陆页面,
2、为什么请求失败??
因为后端存储的 token 不能超过24小时, 首先用户先拿到后端返回的token,存起来,等超过24小时在用这个token去请求, 发现超时,登陆失败,就跳转登陆页
3、如何获取 token ?
登陆–》用户名密码———〉base64转码,请求接口,返回token,使用cookie存储

5、在 this.default.timeout 增加最大超时。
1、如何判定接口超时??

在 interceptors.request 首先记录了创建 request-time 时间, 12:00
在 interceptors.response 中响应接口时间 12:04,data.config[‘request-time’], 发现时长超过3s,给控制台打印日志

2、封装全局 loading

2.1、在 interceptors.request 中

	axios.interceptors.request.use(config => {
        let reqObj = {},
        key = `${config.url}_${Date.now()}`
        reqObj[key] = false
        // 添加一个延时器,所有同步都执行完之后在显示loading
        // 只要每个拦截器请求时就需要启动全局loading,每启动一个loading,后一个会clearTimeout的状态,直到最后一个启动loading
        // 等每个都执行完成之后,关闭自己的url在 reqObj中的开关
        // 最后每请求完成一个需要在 requestArr 删除一个url相关数据,直到为0,关闭loading
        let data = {
  start: new Date().getTime(),
  startTime: dateFormat(new Date()),
  url: config.url
}
requestArr.push(data)

let timer = setTimeout(() => {
  clearTimeout(timer)
  if (!reqObj[key]) { 
    if (isPc()) {
      pc.loading.show()
    } else {
      app.loading.show()
    }
  }
}, 500)


2.2、在 interceptors.response 中
axios.interceptors.response.use(data => {
  reqObj[key] = true 先将记录的某个url的开关关闭
  
     try {
      requestArr.forEach((item, index) => {
        if (item.url === data.config.url) {
          requestArr.splice(index, 1)
        }
      })
      //数组为空 或者 全部都是不需要打开loading的则关闭loading
      if (requestArr.length === 0) { //关闭loading
        hideLoading()
      }

      if (forceCloseTimer) {
        clearTimeout(forceCloseTimer)
      }

      //临时解决loading不消失的问题
      forceCloseTimer = setTimeout(() => {
        clearTimeout(forceCloseTimer)
        hideLoading()
        return
      }, 1000)

    } catch (error) {
      hideLoading()
    }
})
4、根据code返回登陆页面
4.1、(code === 297 || code === 299) 认证失败
if (!PSMU.isEmt(data.data['code']) && (data.data.code === 297 || data.data.code === 299)) {
  let whiteList = ['login']
  if (whiteList.indexOf(currentpath) === -1) {
      PSMU.router.push('/login')
  }
  如果没有其他异常操作,
  return data 提前结束路由response拦截\
 }

4.2 第二天打开前一天的页面,会跳转让重新登陆
  是因为前端存储的cookie中的token为24小时, 第二天会获取不到,后端发现没有token,会提示认证失败,跳转登陆页面
   // 是否有token,存在:增加到headers['Authorization'] = get.token()
    if (PSMU.isValidToken()) {
      config.headers[PSMU.tokenName] = PSMU.getToken()
    }
  
4.3 如何获取token, 用户点击登陆,会获取到token,向下传递,如果没有责登陆失败
  .post('/xxxx/auth/user/loginUrl', {msg: postMsg})
    .then(res => {
        if (res.data.token) {
            PSMU.setToken(res.data.token)
            resolve()
        } else {
            reject(new Error('登录失败'))
        }
    })
    .catch(err => {
        reject(new Error('登录失败'))
    })

5、怎么使用呢,因为在当天开发完成,不关电脑,重新请求接口,

cookie/session/localStorage 区别??请看下一篇文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值