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

Node.js调用Mailchimp API遇请求过多,求批量接口实现方案

解决Mailchimp大型受众列表获取邮箱的请求限制与批量接口实现

一、先修复现有代码的问题(解决Too Many Requests和Promise拒绝)

你遇到的Too Many Requests是因为Mailchimp API有请求频率限制(免费版通常每分钟10次请求,付费版配额更高),而且你的代码存在三个关键问题:

  • 调用getArrayEmailMembersFromMailchimpListID时未使用await,导致所有请求几乎同时发起,瞬间突破频率限制
  • 没有处理Promise的拒绝逻辑,一旦API请求失败就会抛出未捕获的异常
  • 循环内的请求没有做节流控制,完全不等待前一个请求完成就发起下一个

这里给你修改后的完善版本,加入请求节流、错误捕获和自动重试逻辑:

var mailchimpMarketing = require("@mailchimp/mailchimp_marketing");
mailchimpMarketing.setConfig({ 
  apiKey: "MY API KEY", 
  server: "MY SERVER", 
});

// 封装延迟函数,用来控制请求间隔
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

async function getArrayEmailMembersFromMailchimpListID(listID, offset , count){
  try {
    const response = await mailchimpMarketing.lists.getListMembersInfo(listID, {offset, count});
    const emailsMailchimp = response.members.map(member => member.email_address);
    console.log(`获取了 ${emailsMailchimp.length} 个邮箱,当前偏移量:${offset}`);
    return emailsMailchimp;
  } catch (error) {
    console.error(`获取成员失败(偏移量${offset}):`, error.message);
    // 遇到429限流错误时,根据API返回的retry-after头等待后重试
    if (error.status === 429) {
      const retryAfter = parseInt(error.response.headers['retry-after']) || 60;
      console.log(`请求过于频繁,将等待 ${retryAfter} 秒后重试`);
      await delay(retryAfter * 1000);
      return getArrayEmailMembersFromMailchimpListID(listID, offset, count);
    }
    throw error;
  }
}

async function getEmailsAccordingSize(listID){
  try {
    const response = await mailchimpMarketing.lists.getListMembersInfo(listID);
    let offset = 0;
    const totalItems = response.total_items;
    const allEmails = [];
    
    console.log(`开始获取 ${totalItems} 个成员邮箱`);
    
    do {
      const count = Math.min(1000, totalItems - offset); // 最后一次请求适配剩余数量
      const emails = await getArrayEmailMembersFromMailchimpListID(listID, offset, count);
      allEmails.push(...emails);
      offset += count;
      // 每分钟最多10次请求,所以每6秒发起一次新请求
      await delay(6000);
    } while (offset < totalItems);
    
    console.log(`全部获取完成,共收集到 ${allEmails.length} 个邮箱`);
    return allEmails;
  } catch (error) {
    console.error('获取邮箱列表失败:', error.message);
    throw error;
  }
}

// 执行并处理最终异常
getEmailsAccordingSize("MY LIST ID")
  .catch(error => console.error('最终执行错误:', error.message));

修改点说明:

  • 加入delay函数控制请求间隔,严格遵守API频率限制
  • 给所有异步操作添加await,确保请求串行执行
  • 新增错误捕获与自动重试逻辑,针对限流错误做针对性处理
  • 统一收集所有邮箱到一个数组返回,方便后续使用
  • 适配最后一次请求的数量,避免请求超出总成员数

二、使用Mailchimp批量接口实现(更适合大型列表)

批量接口是Mailchimp专为大规模数据操作设计的异步方案,无需手动控制请求频率,非常适合37000条这种量级的列表。下面是具体实现步骤:

1. 核心逻辑说明

批量接口允许你提交一个包含多个API请求的"作业",Mailchimp后台会异步执行所有请求,完成后你可以通过作业ID查询结果。对于获取成员列表,我们可以生成多个GET /lists/{list_id}/members请求(每个请求拉取1000条),打包成批量作业提交即可。

2. 具体代码实现

var mailchimpMarketing = require("@mailchimp/mailchimp_marketing");
mailchimpMarketing.setConfig({ 
  apiKey: "MY API KEY", 
  server: "MY SERVER", 
});

async function createBatchJobForListMembers(listID) {
  try {
    // 先获取列表总成员数
    const listInfo = await mailchimpMarketing.lists.getListMembersInfo(listID);
    const totalItems = listInfo.total_items;
    const batchOperations = [];
    
    // 生成批量操作的请求数组
    for (let offset = 0; offset < totalItems; offset += 1000) {
      const count = Math.min(1000, totalItems - offset);
      batchOperations.push({
        method: "GET",
        path: `/lists/${listID}/members?offset=${offset}&count=${count}`,
        operation_id: `get-members-${offset}` // 唯一标识每个操作,方便后续匹配结果
      });
    }
    
    // 创建批量作业
    const batchResponse = await mailchimpMarketing.batches.create({
      operations: batchOperations
    });
    
    const batchId = batchResponse.id;
    console.log(`批量作业已创建,ID:${batchId},等待后台执行完成`);
    
    // 轮询检查作业状态(每30秒检查一次)
    let jobStatus = "pending";
    while (jobStatus === "pending" || jobStatus === "processing") {
      await delay(30000);
      const jobInfo = await mailchimpMarketing.batches.get(batchId);
      jobStatus = jobInfo.status;
      console.log(`当前作业状态:${jobStatus},完成进度:${jobInfo.completed_operations}/${jobInfo.total_operations}`);
    }
    
    if (jobStatus === "finished") {
      // 收集所有操作的结果
      const allEmails = [];
      for (const op of batchOperations) {
        const result = await mailchimpMarketing.batches.getOperation(batchId, op.operation_id);
        if (result.status_code === 200) {
          const members = JSON.parse(result.response).members;
          const emails = members.map(m => m.email_address);
          allEmails.push(...emails);
        } else {
          console.error(`操作 ${op.operation_id} 失败:`, result.response);
        }
      }
      
      console.log(`批量作业完成,共获取 ${allEmails.length} 个邮箱`);
      return allEmails;
    } else {
      throw new Error(`批量作业执行失败,状态:${jobStatus}`);
    }
    
  } catch (error) {
    console.error('批量作业处理失败:', error.message);
    throw error;
  }
}

// 复用延迟函数
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

// 执行批量作业
createBatchJobForListMembers("MY LIST ID")
  .catch(error => console.error('最终执行错误:', error.message));

批量接口的优势

  • 无需手动处理请求频率,Mailchimp后台自动控制执行节奏
  • 适合超大型列表(几十万甚至更多),完全避免限流问题
  • 异步执行特性,即使中途断开连接,后续仍可通过作业ID查询结果

总结

  • 如果列表规模在几万条以内,修改现有代码加上节流和错误处理就足够稳定
  • 如果是超大型列表,优先使用批量接口,效率更高且更省心

内容的提问来源于stack exchange,提问作者Samy Rharade

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:58:13