如何降低请求速率?解决请求过快引发net::ERR_INSUFFICIENT_RESOURCES错误并实现每20ms发起一次请求
Fixing the net::ERR_INSUFFICIENT_RESOURCES Error with Request Throttling
Hey there! Let's get your request rate sorted out so you don't hit that Google resource error anymore. The problem with your current code is two-fold:
- You're immediately calling
getData(symbol)insidesetTimeoutinstead of passing a function reference. That means all your requests fire off almost at the same time, not after the delay. - Even if you fixed the setTimeout syntax, you'd still be scheduling all requests at once—they'd just all wait 5 seconds then hit the server in a flood.
To get a consistent 20ms delay between each request, we need to process your symbols one after another, not all at once. Here are two straightforward ways to do this:
Option 1: Recursive Processing (Great for Older Browser Support)
This approach uses a recursive function to handle each symbol, waiting 20ms after the previous request completes before starting the next one:
const symbolsArr = reader.result.split("\n").map((str) => str.trim()); const error_symbols = []; // Declare variables properly with const/let // Recursive function to process symbols one by one function processSymbols(index = 0) { // Exit condition: we've processed all symbols if (index >= symbolsArr.length) { console.log("All symbols processed!", error_symbols); return; } const currentSymbol = symbolsArr[index]; getData(currentSymbol) .finally(() => { // Wait 20ms, then process the next symbol setTimeout(() => processSymbols(index + 1), 20); }); } // Start the processing processSymbols(); // Updated getData function (returns the Promise chain) function getData(symbol) { return fetch( `https://cors-anywhere.herokuapp.com/https://eodhistoricaldata.com/api/fundamentals/${symbol}?api_token=你的秘钥`, { method: "get" } ) .then((res) => { if (res.ok) { return res.json(); } else { throw new Error(`Symbol ${symbol} is 'empty'`); } }) .then((data) => { console.log(data); const myJSON = JSON.stringify(data); saveFile(myJSON, `${symbol}-json.txt`, "text/plain"); }) .catch((error) => { error_symbols.push(symbol); console.error(`Failed to fetch ${symbol}:`, error); }); }
Option 2: Async/Await (Cleaner, Modern Syntax)
If you're targeting modern browsers, using async/await makes the code even more readable. We'll loop through each symbol, await the request, then wait 20ms before moving to the next:
const symbolsArr = reader.result.split("\n").map((str) => str.trim()); const error_symbols = []; // Async function to handle all symbols sequentially async function processAllSymbols() { for (const symbol of symbolsArr) { try { // Wait for the current request to finish await getData(symbol); } catch (error) { console.error(`Error with ${symbol}:`, error); } // Wait 20ms before the next request await new Promise(resolve => setTimeout(resolve, 20)); } console.log("All symbols processed!", error_symbols); } // Kick off the process processAllSymbols(); // Keep your getData function (just make sure it returns the Promise) function getData(symbol) { return fetch( `https://cors-anywhere.herokuapp.com/https://eodhistoricaldata.com/api/fundamentals/${symbol}?api_token=你的秘钥`, { method: "get" } ) .then((res) => { if (res.ok) { return res.json(); } else { throw new Error(`Symbol ${symbol} is 'empty'`); } }) .then((data) => { console.log(data); const myJSON = JSON.stringify(data); saveFile(myJSON, `${symbol}-json.txt`, "text/plain"); }) .catch((error) => { error_symbols.push(symbol); throw error; // Let the outer try/catch handle logging }); }
Key Notes:
- Never call functions directly inside
setTimeout: Use() => getData(symbol)instead ofgetData(symbol)—the latter executes immediately. - Serial vs Parallel: Both approaches ensure requests are sent one at a time with a 20ms gap, which avoids overwhelming the server.
- Error Handling: We keep track of failed symbols in
error_symbolsand log errors so you can debug later.
内容的提问来源于stack exchange,提问作者Adam Szymański
相关产品推荐
相关产品推荐

