如何使用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
相关产品推荐
相关产品推荐

