You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何暂停循环刷新API访问令牌后恢复循环?

问题描述

我有一个使用access token的API,通过循环调用该API更新系统中的用户,代码如下:

while (socketerror == 0 && i < usersJson.length) {
  for (let user of usersJson) {
    functions.push(() => userFunctions.updateUser(url, accessToken, user));
  }
}

我在遍历用户进行更新时,access token会过期,需要在调用函数前刷新令牌。我曾考虑在每个用户处理前加入刷新逻辑:

if (new Date.now() < okapiExpiration) {
  accessToken = function refreshToken(accessToken);
}

但由于操作是并行执行的,担心会重复发起令牌刷新请求导致调用报错。之后我考虑在遍历用户前用while循环刷新,但这样每次都会重启整个用户循环。请问如何实现暂停循环、刷新令牌后继续循环?

解决方案

1. 实现令牌刷新互斥锁,避免重复请求

先封装一个获取有效令牌的函数,用Promise作为锁,确保同一时间只有一个刷新请求执行,其他请求等待锁释放后使用新令牌:

let refreshLock = null; // 存储正在进行的刷新操作Promise

async function getValidAccessToken() {
  // 如果已有刷新请求在处理,直接等待其完成
  if (refreshLock) {
    return refreshLock;
  }

  // 令牌未过期,直接返回当前令牌
  if (Date.now() < okapiExpiration) {
    return accessToken;
  }

  // 发起刷新请求,将Promise赋值给锁
  refreshLock = refreshToken(accessToken).then(newToken => {
    accessToken = newToken;
    // 更新令牌过期时间,需根据实际刷新接口返回值调整
    okapiExpiration = /* 新的过期时间戳 */;
    refreshLock = null; // 刷新完成后释放锁
    return accessToken;
  }).catch(err => {
    refreshLock = null; // 刷新失败也要释放锁,避免死锁
    throw err;
  });

  return refreshLock;
}

2. 改造循环逻辑,实现暂停续更

放弃直接批量生成并行任务的方式,改用async/await控制循环流程,每批(或每个)用户处理前先确保令牌有效,自然实现"暂停-刷新-继续"的效果:

分批并行处理(效率更高)

async function updateUsersInBatches(users, batchSize = 5) {
  let currentIndex = 0;
  while (socketerror === 0 && currentIndex < users.length) {
    // 先获取有效令牌,自动处理刷新逻辑
    const validToken = await getValidAccessToken();
    // 截取当前批次的用户
    const batch = users.slice(currentIndex, currentIndex + batchSize);
    // 并行处理当前批次的用户更新
    await Promise.all(
      batch.map(user => userFunctions.updateUser(url, validToken, user))
    );
    currentIndex += batchSize;
  }
}

// 调用执行
updateUsersInBatches(usersJson);

串行处理(适合对请求频率有严格限制的场景)

async function updateUsersSerial(users) {
  let currentIndex = 0;
  while (socketerror === 0 && currentIndex < users.length) {
    const validToken = await getValidAccessToken();
    // 逐个更新用户,完成后再处理下一个
    await userFunctions.updateUser(url, validToken, users[currentIndex]);
    currentIndex++;
  }
}

3. 兼容原有函数数组的改造方案

如果需要保留原有的"收集函数再执行"的模式,可以在每个更新函数内部先获取有效令牌,利用锁机制避免重复刷新:

while (socketerror == 0 && i < usersJson.length) {
  for (let user of usersJson) {
    // 将每个更新操作改为异步函数,先确保令牌有效
    functions.push(async () => {
      const validToken = await getValidAccessToken();
      return userFunctions.updateUser(url, validToken, user);
    });
  }
}

// 执行所有更新操作时用Promise.all
// await Promise.all(functions);

内容的提问来源于stack exchange,提问作者Nimrod Yanai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 19:50:17