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

解决Gmail API 429限流:在JavaScript的map中添加请求缓冲

解决Gmail API调用时的429 (rateLimitExceeded) 错误

问题原因

你之前加的delay无效,是因为Promise.all会一次性启动所有异步请求——每个map里的请求几乎同时发出去,delay只是在单个请求完成后等待,根本没控制住并发量,自然还是触发限流。

可行解决方案

1. 串行请求(适合小批量邮件)

用for循环替代map+Promise.all,逐个发起请求,每次请求后等待一段时间,确保不会同时触发大量请求:

const messageDataList = [];
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

for (const message of messages || []) {
  const data = await contacts.getSentGmailData(accessToken, message.id);
  messageDataList.push(data);
  await delay(500); // 可根据实际限流情况调整延迟时长
}

2. 并发控制(适合大批量邮件)

限制同时发起的请求数量(比如每次最多5个),既保证效率,又不超过API速率限制。以下是自定义并发控制的实现:

async function processMessagesWithConcurrency(messages, accessToken, concurrency = 5) {
  const results = [];
  const runningTasks = [];

  for (const message of messages || []) {
    const task = contacts.getSentGmailData(accessToken, message.id)
      .then(data => {
        results.push(data);
        // 移除已完成的任务
        const idx = runningTasks.indexOf(task);
        if (idx !== -1) runningTasks.splice(idx, 1);
      });

    runningTasks.push(task);

    // 达到并发上限时,等待任意一个任务完成
    if (runningTasks.length >= concurrency) {
      await Promise.race(runningTasks);
    }
  }

  // 等待剩余所有任务完成
  await Promise.all(runningTasks);
  return results;
}

// 使用示例
const messageDataList = await processMessagesWithConcurrency(messages, accessToken, 5);

3. 基于Retry-After的重试机制

Gmail API返回429时,响应头会携带Retry-After字段(单位秒),告诉你需要等待多久再重试。可以在getSentGmailData里加入重试逻辑:

async function getSentGmailData(accessToken, messageId, retries = 3) {
  try {
    const response = await fetch(`https://gmail.googleapis.com/gmail/v1/users/me/messages/${messageId}`, {
      headers: { Authorization: `Bearer ${accessToken}` }
    });

    if (response.status === 429) {
      if (retries <= 0) throw new Error('多次重试后仍触发速率限制');
      const retryAfter = parseInt(response.headers.get('Retry-After')) || 5;
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      return getSentGmailData(accessToken, messageId, retries - 1);
    }

    if (!response.ok) throw new Error(`API请求失败: ${response.status}`);
    return response.json();
  } catch (error) {
    throw error;
  }
}

最佳实践

建议把并发控制和重试机制结合使用:既控制同时发起的请求数,避免触发限流;又在偶尔触发429时,根据API提示自动重试,保证任务完成。

内容的提问来源于stack exchange,提问作者vaibhav deep

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:55:47