项目中首页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)
})
})
}
}
})
}
}
}