You need to enable JavaScript to run this app. 使用setInterval每2秒轮询POST请求更新out.rule时触发json解析报错
优惠活动
大模型
产品
解决方案
定价
更多

使用setInterval每2秒轮询POST请求更新out.rule时触发json解析报错

轮询报body stream already read的问题排查与修复

问题成因

  • 初始化阶段仅执行1次fetch()调用,将返回的Promise赋值给fetchURL,后续所有定时逻辑都在复用这个单次请求的结果。
  • Fetch API的Response对象采用流读取机制,响应体流一旦被.json()、.text()等方法读取,就会被完全消耗,无法二次读取。每2秒对同一个已经被读过的Response重复调用.json(),就会直接触发body stream already read的报错。
  • 这种写法本质上没有按间隔发新的请求,永远只能拿到第一次请求的响应结果,自然无法获取服务端最新的out.rule数据。
  • 附带逻辑bug:原代码里的console.log('Error')写在setInterval的同步执行分支,和请求的catch逻辑完全分离,不管请求成功失败都会打错误日志,完全起不到错误监控的作用。

修复实现

按照以下逻辑调整:

  • 把完整的POST请求逻辑封装为独立函数,每次定时触发时重新发起请求,不复用已消耗的响应对象。
  • 增加请求状态锁,避免上一次请求耗时超过2秒的轮询间隔时,出现请求堆叠、旧响应覆盖新数据的竞态问题。
  • 将错误捕获、日志打印移入请求流程的catch分支,精准捕获请求、数据解析阶段的异常。

修复后的参考代码:

// 封装独立的规则数据拉取逻辑,每次调用都会重新发起完整请求
async function fetchRuleData() {
  const response = await fetch("myURL", {
    headers: {
      "accept": "application/json, text/plain, */*",
      "accept-language": "vi-VN,vi;q=0.9,fr-FR;q=0.8,fr;q=0.7,en-US;q=0.6,en;q=0.5",
      "content-type": "application/json;charset=UTF-8",
      "sec-fetch-dest": "empty",
      "sec-fetch-mode": "cors",
      "sec-fetch-site": "cross-site"
    },
    referrerPolicy: "strict-origin-when-cross-origin",
    body: "{myBody}",
    method: "POST",
    mode: "cors",
    credentials: "omit"
  });
  return response.json();
}

// 简单请求锁,避免请求堆叠
let isPolling = false;
async function executePoll() {
  // 上一次请求未完成就跳过本次轮询
  if (isPolling) return;
  isPolling = true;
  try {
    const out = await fetchRuleData();
    // 匹配规则时执行业务逻辑
    if (out.rule === 'admin') {
      // 业务逻辑占位
    }
  } catch (err) {
    console.error('轮询拉取规则数据失败:', err);
  } finally {
    // 无论请求成功失败,释放锁
    isPolling = false;
  }
}

// 启动2000ms间隔的轮询
const refreshIntervalId = setInterval(executePoll, 2000);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.11 21:45:04