刷新token并执行token之前的请求 - Promise等待继续执行

项目中首页app需要获取access_token后执行3-4个请求,但是每过5分钟token会失效,这个时候判断用户是否还需要请求,如果需要,则刷新token,未响应则不需要。 而多个请求,每个请求都需要先获取access_token后,携带access_token才能后续请求,如获取用户信息,用户中心等页面,而每个接口是独立的,则会请求多次access_token,肯定是不合理的。

需求:需要发起多个请求B(此处使用Promise),但是在发起Promise前需要获取一个通用的请求A,需要实现发起多个请求B,但是通用请求A只请一个,其他请求等待请求A执行完成后再去执行。


解决思路:使用Promise无返回结果会一直挂起请求,直到有返回结果时才会执行。

let isRequestToken = false // 是否有请求Token
let axiosToken = null // 请求A的Promise结果
// 设置Token
function setToken (tokenName) {
  // 返回Promis
  return new Promise((resolve, reject) => {
  	// 判断如果有发起过请求Token并且已经有Token的Promise结果(此时可能是pending状态,则直接返回Promise状态)
    if (isRequestToken && axiosToken) return resolve(axiosToken);
    // 第一请求,将请求flag开关打开
    isRequestToken = true
    // 设置token
    axiosToken = new Promise((resolve) => {
      axios.get('/api.php/oauth/2.0/token')
      .then((res) => {
        if (res.code === 200) {
          localStorage.setItem(tokenName, JSON.stringify(res.data))
        }
        resolve(res.data)
      })
      .catch((err) => {
        isRequestToken = false
        reject(err)
      })
    })
    // 将请求结果返回(此时可能是pending状态)
    resolve(axiosToken)
  })
}

// 刷新Token
function refreshToken (tokenName) {
  return new Promise((resolve, reject) => {
    // 如果已经有获取access_token则直接返回请求结果
    if (isRequestToken && axiosToken) return resolve(axiosToken);
	
	// 如果没有获取access_token则发起请求
    isRequestToken = true
    // 请求access_token
    axiosToken = new Promise((resolve) => {
      axios.post('/api.php/oauth/2.0/refresh_token', {
        refresh_token: Token.refresh_token
      })
      .then((res) => {
        if (res.code === 200) {
          localStorage.setItem(tokenName, JSON.stringify(res.data))
        } else {
          localStorage.removeItem(tokenName)
        }
        isRequestToken = false
        resolve(res.data)
      })
      .catch((err) => {
        isRequestToken = false
        reject(err)
      })
    })
    resolve(axiosToken)
  })
}

还有一个MetaMask唤起钱包功能思路也是一样。
请求数据,如钱包余额、币种查询等,需要先获取钱包地址后再去执行查询方法,此时查询的方法是独立的,此时需要多个地方使用ethereum.enable()方法,获取钱包地址后再去执行查询。

let isEnable = false // 是否请求过
let actionEnable = null // 请求结果 <Promise>

export default {
	state () {
		return {
			coinbase: ''
		}
	},
	mutations: {
		// 写入钱包地址
		writeCoinbase (state, address) {
			state.coinbase = address
		}
	},
	actions: {
	    linkWallet ({ commit, state }) {
	    	return new Promise((resolve) => {
				if (state.coinbase) {
					resolve(state.coinbase)
				} else {
              		if (isEnable && actionEnable) { // 请求过,返回请求结果
                		actionEnable.then(resolve)
              		} else { // 未请求,唤起钱包并存储Promise结果
		                isEnable = true
		                actionEnable = new Promise((resolve) => {
		                  window.ethereum.enable().then((res) => {
		                    commit('onWriteAddress', res[0])
		                    resolve(res[0])
		                  }).catch((err) => {
		                    resolve(false)
		                  })
		                })
              		}
				}
			})
	    }
	}
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用axios发送请求时,我们可以通过Promise无痛刷新token,确保在token过期之后,通过刷新token的方式继续发送请求。 以下是实现该功能的一种方式: 首先,我们需要创建一个axios实例,并设置请求拦截器。在请求拦截器中,我们通过判断是否存在有效的token来决定是否需要刷新token。 ```javascript import axios from 'axios'; // 创建axios实例 const instance = axios.create(); // 设置请求拦截器 instance.interceptors.request.use( (config) => { // 将token添加到请求头 const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); } ); ``` 接下来,我们需要在响应拦截器中处理token刷新的逻辑。当接收到后端的响应时,我们可以在响应拦截器中判断是否返回了一个特定的错误码,表示token已过期。如果是,则我们需要使用refreshToken刷新token。 ```javascript // 设置响应拦截器 instance.interceptors.response.use( (response) => { // 处理响应数据 return response; }, (error) => { // 判断是否为token过期的错误码 if (error.response && error.response.status === 401) { const originalRequest = error.config; // 使用refreshToken刷新token return refreshToken().then((newToken) => { // 刷新成功后将新token保存到本地存储 localStorage.setItem('token', newToken); // 重新发送原始请求 originalRequest.headers.Authorization = `Bearer ${newToken}`; return axios(originalRequest); }).catch((refreshError) => { // 刷新失败处理逻辑,跳转到登录页面等 console.error('刷新token失败:', refreshError); // 重定向到登录页面等 window.location.href = '/login'; return Promise.reject(refreshError); }); } return Promise.reject(error); } ); ``` 在上面的代码中,refreshToken函数用于实现刷新token的逻辑。它可以发送一个特殊的刷新token请求,并返回新的token。在刷新成功后,我们将新的token保存到本地存储中,并重新发送原始请求。 需要注意的是,如果刷新token失败,我们需要根据具体业务需求进行相应的处理,例如跳转到登录页面,弹窗提示重新登录等。 最后,我们可以使用该axios实例来发送请求,它自动判断是否需要刷新token,并且无需手动处理token过期的情况。 希望以上回答能对您有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值