刷新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 // 请求结果 

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)
		                  })
		                })
              		}
				}
			})
	    }
	}
}

你可能感兴趣的:(项目难题)