【问题标题】:Error when making multiple ajax calls进行多个 ajax 调用时出错
【发布时间】:2016-06-25 04:31:43
【问题描述】:

我正在尝试读取包含 JSON 数据的 URL 数组。我正在尝试遍历数组并为每个 URL 加载 JSON。但是我遇到了错误问题(Firebug 中的网络错误 429),这让我相信这是发送太多请求的问题。我修改并简化了我的代码,使其与 jsfiddle 中列出的一样。我目前正在尝试使用 setTimeout 来延迟 ajax 调用,但在一定数量的 ajax 调用之后我仍然收到错误。

JSBINhttp://jsfiddle.net/s7s4cx9y/3/

var dataURL = [
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380673/timeline?gameHash=ee3b8fd05dd64784",
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380609/timeline?gameHash=9dd207ff3ebfd598",
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380641/timeline?gameHash=828ef9a4dd73bd08", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380241/timeline?gameHash=23c53fb7fed21f53", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380327/timeline?gameHash=84db7440d6c8cfed", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380474/timeline?gameHash=d90ecc8a74124bcf",
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001390143/timeline?gameHash=f8a97528a608655c", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001390158/timeline?gameHash=05abd4c334651b0d", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001390159/timeline?gameHash=2bf6f0a9b1e84151", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001390160/timeline?gameHash=d4005554002839f3", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001410069/timeline?gameHash=39d2712050cd954a", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001410081/timeline?gameHash=12a38a55a9d5cf18", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001410080/timeline?gameHash=46fd67ed4c6dfb68", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001440041/timeline?gameHash=aeba4cc81f453c31", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001440036/timeline?gameHash=5debbe8da795a7cf", 
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001440042/timeline?gameHash=53a746631e808796", "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001440043/timeline?gameHash=4725b07311676885"
];
function test(url, x)
{
    $.ajax({
            url:url,
            dataType:'jsonp',
            async:false,

           error: function (parsedjson, textStatus, errorThrown) {
               $('body').append(
                    "<b>ERROR</b> </br> parsedJson status: " + parsedjson.status + '</br>' + 
                    "errorStatus: " + textStatus + '</br>' + 
                    "errorThrown: " + errorThrown + '</br></br>' + 
                    "URL: " + url + "<br> iterator: X = " + x + "</br></br>");       
           },
           success : function(data) {
               $('body').append(
                    "<b>SUCCESS</b> </br>" +
                    "URL: " + url + "</br> iterator: X = " + x + "</br></br>"); 
           }
     });
}
for(var x = 0; x < dataURL.length; x++)
{
    var proxyUrl = 'https://jsonp.afeld.me/';
    var url = proxyUrl + '?url=' +     encodeURIComponent(dataURL[x] ) + '&callback=?';
    setTimeout(test(url, x), 10000);
}

必须通过代理脚本重定向 URL 以生成正确的 jsonp,如上一个问题中所引用的:Passing JSON from server-side (.NET) to client-side (jQuery)

【问题讨论】:

  • 429 Too Many Requests in short time 被识别为 DDoS 攻击
  • Ajax 给我一个 404 错误。我认为这与请求率有关,这就是我添加 setTimeout 的原因,但即使时间间隔很长,它仍然不会拒绝我访问。

标签: jquery ajax


【解决方案1】:

尝试将async: true 设置为$.ajax() 选项;在 IIFE 中包装对 setTimeout 的调用

for (var x = 0; x < dataURL.length; x++) {
  (function(y) {
    // `y` : `x`
    var proxyUrl = "https://jsonp.afeld.me/";
    var url = proxyUrl + "?url=" 
              + encodeURIComponent(dataURL[y]) + "&callback=?";
    setTimeout(function() {
      test(url, y)
    }, y * 999999);
  }(x))
}

jsfiddle http://jsfiddle.net/s7s4cx9y/4/

【讨论】:

    【解决方案2】:

    这样使用:

    setTimeout(function(){ test(url, x) }, 10000);
    

    否则你的test() 方法会被立即调用:

    setTimeout(test(url, x), 10000);
    

    更新:

    for(var x = 0; x < dataURL.length; x++)
    {
        .....
        setTimeout(function(){ test(url, x) }, 10000*x);
        or
        setTimeout(function(){ test(url, x) }, 1000*x);
    }
    

    【讨论】:

    • 这只会在 10 秒内完成所有呼叫,是吗?
    • 通过该更改,我仍然在 ajax 调用中收到错误,但现在迭代器值 (x) 始终是数组长度 (17)。
    • @TaylorM 在 setTimeout 中设置不同的时间,否则您的请求将在 10 秒内执行
    【解决方案3】:

    这是一个递归解决方案和fiddle

    var dataURL = [
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380673/timeline?gameHash=ee3b8fd05dd64784",
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380609/timeline?gameHash=9dd207ff3ebfd598",
    "https://acs.leagueoflegends.com/v1/stats/game/TRLH3/1001380641/timeline?gameHash=828ef9a4dd73bd08"
    ];
    
    function test(url) {
      return $.ajax({
        url:url,
        dataType:'jsonp',
        error: function (parsedjson, textStatus, errorThrown) {
          $('body').append(
          "<b>ERROR</b> </br> parsedJson status: " + parsedjson.status + '</br>' + 
          "errorStatus: " + textStatus + '</br>' + 
          "errorThrown: " + errorThrown + '</br></br>' + 
          "URL: " + url + "<br></br>");
        },
        success : function(data) {
          $('body').append(
          "<b>SUCCESS</b> </br>" +
          "URL: " + url + "</br></br>"); 
        }
    });
    }
    
    (function iterateUrls() {
      var proxyUrl = 'https://jsonp.afeld.me/';
      var u = dataURL.shift();
      if(!u) { return; }
      var url = proxyUrl + '?url=' + encodeURIComponent(u) + '&callback=?';
      setTimeout(function() { 
        test(url).then(function() { iterateUrls(); });
      }, 1000);
    })();
    

    超级奖励编辑!:

    你根本不需要 setTimeout!如果您一次只有一个请求在进行中,则请求成功。这将为您节省大量时间:

    (function iterateUrls() {
      var proxyUrl = 'https://jsonp.afeld.me/';
      var u = dataURL.shift();
      if(!u) { return; }
      var url = proxyUrl + '?url=' + encodeURIComponent(u) + '&callback=?';
      test(url).then(iterateUrls);
    })();
    

    您可以进行一些测试,看看您是否可以同时处理多个请求。

    【讨论】:

      【解决方案4】:

      您正在访问 Riot Games API。它以a rate limiting measure 的形式发送429 个响应以及一个Retry-After 标头以及您应该等待的时间。它还会为丢失的匹配发送 404 响应,有时甚至包括应该存在但由于某些生产/缓存原因不可用的匹配。

      顺便说一句,典型的 Riot API 开发人员计划成员会获得 API 密钥,他们应该在请求中包含这些密钥。每个键都有自己的速率限制。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-21
        • 2015-06-17
        • 2020-07-20
        • 2015-09-26
        • 2012-01-11
        • 1970-01-01
        • 1970-01-01
        • 2012-10-12
        相关资源
        最近更新 更多