如何在循环中处理大量Ajax请求并防止;“请求太多”;使用JavaScript

如何在循环中处理大量Ajax请求并防止;“请求太多”;使用JavaScript,javascript,jquery,ajax,xmlhttprequest,Javascript,Jquery,Ajax,Xmlhttprequest,我试图从web服务中保存一些信息,这是大量的数据,我必须发出大量Ajax请求,在许多请求如此之快之后,服务器只是抛出“太多请求”,这是有意义的 我的代码如下所示: function getDataFromWS() { define some vars $ make an ajax request to MY database to get every item i will request on the external WS (that query returns l

我试图从web服务中保存一些信息,这是大量的数据,我必须发出大量Ajax请求,在许多请求如此之快之后,服务器只是抛出“太多请求”,这是有意义的

我的代码如下所示:

function getDataFromWS()
{
    define some vars
    $ make an ajax request to MY database to get every item i will request on the external WS 
    (that query returns like 150 items to arrayFromResponse)
    
    //Loop into the array with 150 items
    arrayFromResponse.forEach((element)=>{
        //For loop to make request for each day of the month e.g. August 31 days
        for(let i = 1; i <= 31; i++){
            //change uri to match each day using i
            uriData.date = '2020-08-0'+i;

             //This is where after many requests it throws error 429 "Too many"
                $.ajax({
                    data: uriData,
                    url: uri,
                    type: 'GET',
                    async: false,
                    success : function(response){
                        
                            //Save data from response to some arrays I use
                    
                    },
                    error: function(response){
                        console.log(response);
                        console.log('Error');
                    }
                });
        } 
    })
    //After all that looping and requests make a CSV file
    buildCSVfile(dataFromResponses);
}
函数getDataFromWS() { 定义一些变量 $makeajax请求我的数据库,以获取我将在外部WS上请求的每个项目 (该查询将向arrayFromResponse返回大约150个项目) //循环到包含150项的数组中 arrayFromResponse.forEach((元素)=>{ //对于循环,每月的每一天都要提出请求,例如8月31日
对于(让i=1;i我建议使用jQuery-Deffered,因为您已经使用了jQuery

阅读jQuery以了解内部工作原理。 它基本上实现了一个基于承诺的系统

您的代码可能会以如下方式结束:

函数getDataFromWS() { var DEREFERED=新的$.DEREFERED(); var dataFromResponses=[]; //定义一些变量 //$makeajax请求我的数据库,以获取我将在外部WS上请求的每个项目 //(该查询将向arrayFromResponse返回大约150个项目) var uri=”https://jsonplaceholder.typicode.com/todos/"; var arrayFromResponse=[“一些数据”]; //循环到包含150项的数组中 arrayFromResponse.forEach((元素)=>{ //对于循环,每月的每一天都要提出请求,例如8月31日
对于(让i=1;i我认为这对后端来说是一个挑战-它的API应该支持通过一个请求完成这项任务。 但如果您确定需要发出许多单独的请求,只需使用并发限制():

从“c-promise2”导入CPromise;
从“jquery”导入$;
异步函数getDataFromWS(url,并发){
返回CPromise.all(
函数*(){
for(设i=1;i<32;i++){
常量数据={日期:“2020-08-0”+i};
收益率$0.ajax({
数据:uriData,
网址,
键入:“获取”,
数据类型:“json”,
异步:true
});
}
},
{并发性}
);
}
const buildCSVfile=async(响应)=>{
log(`Done:`,responses.map(JSON.stringify));
};
(异步()=>{
const data=等待getDataFromWS(
`https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-延迟=1s`,
10//并发请求限制
);
等待构建CSVFile(数据);
})();

“我需要所有这些代码都是同步的”为什么?BTW,如果你添加代码> SETTIMEOUT ,那么它将不再是同步的。@ HereticMonkey因为有保存数据的CSV文件,我只需要对每个Ajax请求延迟一次,在4500个请求的末尾,将文件保存在所有的文件中。它现在工作,但只需要50个请求。请考虑一个不同的技术。'不需要同步执行。查看对它的回答在您的代码段上非常有效,但在.done函数的console.log(dataFromResponses)中,如果我放置console.log(dataFromResponses),它只会像第一个响应id:i一样打印在返回之前,它会打印包含31个响应的整个数组…感谢您的回答,因此使用此代码,我在多次调用API时不会出现“太多请求”错误?或者使用此代码,我能够使用延迟,这对我来说是有意义的,不会出现此错误。此代码将以“同步”方式处理请求方式。因此,调用不会同时运行。在一定时间内可以进行的调用量仍可能受到服务器的限制。请对服务器/后端进行一点试验,看看是否遇到任何问题。
import CPromise from "c-promise2";
import $ from "jquery";

async function getDataFromWS(url, concurrency) {
  return CPromise.all(
    function* () {
      for (let i = 1; i < 32; i++) {
        const uriData = { date: "2020-08-0" + i };
        yield $.ajax({
          data: uriData,
          url,
          type: "GET",
          dataType: "json",
          async: true
        });
      }
    },
    { concurrency }
  );
}

const buildCSVfile = async (responses) => {
  console.log(`Done: `, responses.map(JSON.stringify));
};

(async () => {
  const data = await getDataFromWS(
    `https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-delay=1s`,
    10 // concurrent request limit 
  );
  await buildCSVfile(data);
})();