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

Deno 1.44.4中基于setTimeout的限流器请求排队问题求助

问题根源

你的限流器逻辑是批量清空所有等待请求,然后等待5秒再进入下一轮,而非你预期的「请求间添加延迟」:

  • 当第一个请求进来,callLimiter启动limiter,limiter会一次性处理队列里的所有请求,然后设置5秒定时器
  • 在这5秒等待期间,新进来的请求只会被加入requests队列,但因为timerInstance不为0,callLimiter不会触发新的limiter执行
  • 只有等5秒定时器结束,limiter才会再次运行,批量处理这段时间积累的所有请求,导致超过2个请求时,后续请求必须等待定时器完成才能响应
修复代码

改成逐个处理队列请求,每个请求之间间隔5秒的逻辑,修改后的完整代码如下:

const headers = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Headers": "*" }

const REQUEST_LIMITER = { timerInstance: null, requests: new Map() };

Deno.serve({ port: 9000 }, requestHandler);

async function requestHandler(req: Request) {
  console.log("----- New Request recieved -----");

  if (req.url.endsWith("test")) return await testController();

  return Response.json({ status: "error", message: "Invalid API endpoint" }, { status: 404, headers });
}

async function testController() {
  return new Promise((resolve) => {
    const requestId = crypto.randomUUID();
    REQUEST_LIMITER.requests.set(requestId, { resolve });
    callLimiter();
  }).then(data => {
    return Response.json({ status: "success", data }, { status: 200, headers });
  });
}

function callLimiter() {
  // 如果没有正在运行的定时器,且队列有请求,启动处理流程
  if (!REQUEST_LIMITER.timerInstance && REQUEST_LIMITER.requests.size > 0) {
    processNextRequest();
  }
}

function processNextRequest() {
  // 取出队列中的第一个请求
  const [requestId, { resolve }] = REQUEST_LIMITER.requests.entries().next().value;
  REQUEST_LIMITER.requests.delete(requestId);

  // 响应当前请求
  resolve("Resolved");

  // 如果队列还有请求,设置5秒延迟后处理下一个
  if (REQUEST_LIMITER.requests.size > 0) {
    REQUEST_LIMITER.timerInstance = setTimeout(() => {
      REQUEST_LIMITER.timerInstance = null;
      processNextRequest();
    }, 5000);
  } else {
    // 队列为空,清空定时器标记
    REQUEST_LIMITER.timerInstance = null;
  }
}
测试页面修复

你的测试代码里fetch未加await,会导致读取response.status时出错,修改后的测试页面代码:

<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
  <button onclick="makeAPICall()">Make Request</button>
  <p id="result"></p>
  <script>
    async function makeAPICall() {
      try {
        const response = await fetch("http://localhost:9000/test");
        if (response.status === 200) {
          const responseData = await response.json();
          // 追加结果,方便查看多个请求的响应顺序
          document.getElementById("result").innerHTML += `<br>${responseData.data}`;
        }
      } catch (err) {
        console.error(err);
      }
    }
  </script>
</body>
</html>
效果验证
  • 连续点击按钮发送多个请求,第一个请求会立即响应
  • 后续每个请求会在前一个请求响应后等待5秒再响应,完全符合「请求间添加延迟」的需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:11:05