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

如何限制浏览器端应用的Discogs API请求频率?

解决Discogs API请求速率限制的本地限流方案

我来帮你搞定这个问题!之前我在做Discogs相关工具的时候也碰到过一模一样的速率限制问题,用任务队列+串行延迟请求的方式就能完美解决,而且不会像你之前用setInterval那样出现空跑循环的情况。

首先先明确Discogs的规则:免费未认证用户是60请求/分钟,认证用户可以提升到240请求/分钟。咱们的核心思路就是让请求严格按照这个频率串行发送,避免并发或者连续快速请求触发超限。

方案1:基于Fetch + Async/Await的队列限流(推荐,适配你的现有代码)

这个方案适配你已经写的getRelease函数,用任务队列来管理所有需要查询的ID,每次只处理一个请求,完成后等待固定间隔再处理下一个:

// 1. 定义全局任务队列,存放需要查询的release ID
const releaseQueue = [];
// 2. 根据Discogs限制设置请求间隔(免费用户60/分钟,留100ms缓冲用1100ms)
const REQUEST_INTERVAL = 1100;

// 3. 递归处理队列的核心函数
async function processQueue() {
  // 队列为空时终止递归
  if (releaseQueue.length === 0) {
    console.log('所有Release查询完成!');
    return;
  }

  // 取出队列第一个ID
  const currentId = releaseQueue.shift();

  try {
    // 调用你的getRelease函数获取数据
    const parsedData = await getRelease(currentId);
    // 这里写处理CSV的逻辑,比如把parsedData存入数组或写入文件
    console.log(`成功处理Release ${currentId}`);
  } catch (error) {
    console.error(`处理Release ${currentId}失败:`, error.message);
    // 可选:如果请求失败,把ID放回队列末尾重试
    // releaseQueue.push(currentId);
  }

  // 等待指定间隔后,继续处理下一个请求
  setTimeout(processQueue, REQUEST_INTERVAL);
}

// 4. 你的原有getRelease函数,优化错误处理(新增429超限处理)
function getRelease(id) {
  return fetch(`https://api.discogs.com/releases/${id}`, {
    headers: { 'User-Agent': 'CSV for Discogs/0.1', }
  })
  .then(response => {
    // 处理速率超限(429状态码),读取官方返回的重试等待时间
    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After')) || 10;
      console.log(`触发速率限制,将在${retryAfter}秒后重试`);
      // 等待指定时间后重新发起请求
      return new Promise(resolve => setTimeout(resolve, retryAfter * 1000))
        .then(() => getRelease(id));
    }
    // 处理其他错误状态
    if (!response.ok) {
      throw new Error(`请求失败,状态码: ${response.status}`);
    }
    return response.json();
  })
  .then(parseReleaseData);
}

// 5. 使用方式:把输入文件的ID数组加入队列,启动处理
// 假设你从输入文件读取到的ID数组是inputIds
const inputIds = [12345, 67890, ...]; // 你的30+个Release ID
releaseQueue.push(...inputIds);
// 启动队列处理
processQueue();

方案2:基于XMLHttpRequest的队列限流

如果你的代码还在使用XMLHttpRequest,也可以用类似的队列思路,通过请求完成的回调来触发下一个请求:

const releaseQueue = [];
const REQUEST_INTERVAL = 1100;

function processQueue() {
  if (releaseQueue.length === 0) {
    console.log('所有请求处理完成');
    return;
  }

  const currentId = releaseQueue.shift();
  const request = new XMLHttpRequest();
  
  request.open('GET', `https://api.discogs.com/releases/${currentId}`);
  // 必须设置User-Agent,Discogs强制要求,否则会被拒绝请求
  request.setRequestHeader('User-Agent', 'CSV for Discogs/0.1');
  
  request.onload = function() {
    if (request.status >= 200 && request.status < 300) {
      const data = JSON.parse(request.responseText);
      const parsedData = parseReleaseData(data);
      console.log(`成功处理Release ${currentId}`);
    } else {
      console.error(`处理Release ${currentId}失败,状态码: ${request.status}`);
      // 可选:失败重试
      // releaseQueue.push(currentId);
    }
    // 当前请求完成后,延迟启动下一个
    setTimeout(processQueue, REQUEST_INTERVAL);
  };

  request.onerror = function() {
    console.error(`请求Release ${currentId}时发生网络错误`);
    setTimeout(processQueue, REQUEST_INTERVAL);
  };

  request.send();
}

// 使用方式
const inputIds = [12345, 67890, ...];
releaseQueue.push(...inputIds);
processQueue();

关键注意点

  • 必须设置User-Agent:Discogs API强制要求所有请求携带合法的User-Agent,否则会直接拒绝请求,你的XMLHttpRequest代码片段里没加,一定要补上!
  • 灵活调整间隔:如果你用了Discogs认证(个人访问令牌或OAuth),速率限制提升到240请求/分钟,这时候可以把间隔改成260ms左右(留缓冲)。
  • 错误重试:对于429错误或者网络错误,可以把失败的ID放回队列末尾重试,避免遗漏数据。

内容的提问来源于stack exchange,提问作者double-happiness

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:30:04