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

如何使用JavaScript的setTimeout实现定时服务器请求以避免限流?循环中setTimeout失效问题求助

问题分析与解决方案

你的代码里有两个关键问题导致定时请求没按预期工作,我来帮你拆解并修复:

1. setTimeout 的参数错误

你当前的写法是:

setTimeout(getData(json, i), 1000 * i)

这里getData(json, i)是直接调用函数,会立即执行getData,而不是把它作为延迟执行的回调。setTimeout的第一个参数需要是一个函数引用,而不是函数执行的结果(这里getData没有返回值,实际传的是undefined),所以根本没起到延迟作用。

2. 可选优化:用async/await简化定时逻辑

虽然修复第一个问题就能解决,但结合你已经用async函数的场景,用async/await+延迟Promise的方式,代码会更易读,也能避免循环里的闭包陷阱,逻辑更线性。


修复后的代码方案

方案一:修正setTimeout的回调方式

把getData包装成箭头函数传给setTimeout,确保它在延迟后才执行:

async function initiateSearchExperimental() { 
  const json = await getCollections(); 
  for (let i = 0; i < json.result.data.length; i++) { 
    // 用箭头函数包裹,避免立即执行
    setTimeout(() => getData(json, i), 1000 * i) 
  } 
} 

function getData(json, i) { 
  fetch(`https://howrare.is${json.result.data[i].url}/?for_sale=on&sort_by=rank`)
    .then(function(response) { 
      return response.text(); 
    })
    .then(function(html) { 
      var parser = new DOMParser(); 
      var doc = parser.parseFromString(html, 'text/html'); 
      var priceArray = getPriceArray(doc.querySelectorAll("div.featured_item")) 
      console.log(json.result.data[i].url, curateArrayTwo(priceArray, json.result.data[i])) 
    })
    .catch(function(err) { 
      console.warn('Something went wrong.', err); 
    }); 
}

方案二:用async/await实现线性延迟(更推荐)

这种方式让请求严格按顺序间隔1秒发送,逻辑更清晰,也更容易调试:

async function initiateSearchExperimental() { 
  const json = await getCollections(); 
  for (let i = 0; i < json.result.data.length; i++) { 
    await getData(json, i);
    // 每次请求完成后,等待1秒再执行下一次
    await new Promise(resolve => setTimeout(resolve, 1000));
  } 
} 

// 把getData改成async函数,让它返回Promise
async function getData(json, i) { 
  try {
    const response = await fetch(`https://howrare.is${json.result.data[i].url}/?for_sale=on&sort_by=rank`);
    const html = await response.text();
    var parser = new DOMParser(); 
    var doc = parser.parseFromString(html, 'text/html'); 
    var priceArray = getPriceArray(doc.querySelectorAll("div.featured_item")) 
    console.log(json.result.data[i].url, curateArrayTwo(priceArray, json.result.data[i])) 
  } catch (err) {
    console.warn('Something went wrong.', err); 
  }
}

为什么这样改?

  • 方案一中的箭头函数() => getData(json, i)会被setTimeout存储,到指定时间后才调用getData,真正实现了延迟执行的效果。
  • 方案二用await等待每个请求完成,再等待1秒,完全避免了setTimeout循环中可能出现的时序混乱问题,代码风格也更符合现代异步编程的习惯。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:47:39