我正在将大量数据发布到一个API,该API使用一个令牌,需要每30分钟刷新一次。
当令牌过期时,我如何暂停脚本,刷新令牌,然后从停止时开始继续?
到目前为止,我已经:
const post = await mergedItems.forEach((item, index) => {
return new Promise((resolve, reject) => {
const postBody = `{ "ItemShops": { "ItemShop": [{ "itemShopID": ${item.itemShopID}, "qoh": ${item.qoh} }]}}`
setTimeout(() => {
axios({
url: `${lightspeedApi}/Account/${accountID}/Item/${item.id}.json`,
method: 'put',
headers: authHeader,
data: postBody
}).then(response => {
if (response.status == 401) {
refreshToken()
} else {
console.log(response.data) }
}).catch(err => console.error(err))
}, index * 10000)
})
})
}}
这是一个相当常见的问题,而且并行(哈!) 这里描述的。 您正在并行地启动多个请求,并且可以预期,一旦一个请求收到401响应,其他请求随后也会收到同样的响应。 这意味着它们都开始尝试刷新令牌,也是并行的。
下面是如何应用解决方案的粗略草图:
const makeRequest = async (opts) => {
try {
return axios(opts);
catch (err) {
// not axios throws on >=400 response code, not like fetch
if (err.response && err.response.status === 401) {
await refreshToken();
return makeRequest(opts);
else {
raise err;
}
}
}
现在,您可以公开令牌得到刷新的承诺,并重用它以避免在一个请求已经在运行时发出多个请求:
let refreshPromise;
export const refreshToken = () => {
if (!refreshPromise) {
// start a refresh request only if one isn't in flight
refreshPromise = axios(...).then((res) => {
// ... reset token
refreshPromise = null;
});
}
return refreshPromise;
};