【问题标题】:How to call an ajax function in a for loop [duplicate]如何在for循环中调用ajax函数[重复]
【发布时间】:2016-12-26 11:41:00
【问题描述】:

我是 ajax 和 JavaScript 的新手。 我要做的是多次调用 ajax 函数以从资源中获取某些数据,然后将所有数据“推送”到一个数组中,以便稍后在代码中使用它。这是我的代码。

var arr = [];
var users = ["brunofin", "comster404", "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];

for (i = 0; i < users.length; i++) {
    $.ajax({
        url: "https://api.twitch.tv/kraken/streams/" + users[i],
        success: function(data) {
            arr.push(data);
        },
        error: function(data) {
            arr.push("blank");
        },
        complete: function() {
            if (i == users.length) {
                console.log(arr); //This seem to print even when the condition isn't true
            }
        }
    });
}

代码的问题在于,即使i 不等于users.length,它也会打印到控制台

我的问题是;我如何确保它等到i == users.length 为真后再打印到控制台? 请记住,我仍然希望该过程是异步的。

【问题讨论】:

  • AJAX 是异步的(尽管根据您的代码),也就是说,您永远不知道什么时候会收到响应。所以我觉得这不是正确的方法。但是您可能需要的是async:false [ * 不是这样做的正确方法 * ]
  • 这是您要找的吗? stackoverflow.com/questions/5052543/…
  • 也相关 - 条件不是你想的那样。这里是some more information
  • 你的 if 语句也永远不会为真,i 永远不会等于数组长度。
  • @MageshKumaar 只需调用 ajax 作为 async:false

标签: javascript jquery ajax


【解决方案1】:

您可以尝试使用 async false 调用 ajax,如下所示

$.ajax({
        type: "GET",
        url: remote_url,
        async: false,
        success : function(data) {
            remote = data;
        }
    });

【讨论】:

  • OP说要异步调用。
  • 我希望进程保持异步
【解决方案2】:

在循环中使用闭包并将其与i绑定

var arr = [];
var users = ["brunofin", "comster404", "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];

for (i = 0; i < users.length; i++) {
(function(x){
 $.ajax({
    url: "https://api.twitch.tv/kraken/streams/" + users[x],
    success: function(data) {
      arr.push(data);
    },
    error: function(data) {
      arr.push("blank");
    },
    complete: function() {
      if (i == users.length) {
        console.log(arr); //This seem to print even when the condition isn't true
      }
    }
  });
})(i)
}

【讨论】:

    【解决方案3】:

    你能试试下面的代码吗:

    var arr = [];
    var users = ["brunofin", "comster404", "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var currentIndex = 0;
    PerformAjax(arr, users, currentIndex);
    
    function PerformAjax(arr, users, currentIndex)
    {
        $.ajax({
            url: "https://api.twitch.tv/kraken/streams/" + users[currentIndex],
            success: function(data) {
                arr.push(data);
            },
            error: function(data) {
                arr.push("blank");
            },
            complete: function() {
                currentIndex++;
                if (currentIndex == users.length) {
                    console.log(arr); //This seem to print even when the condition isn't true
                }
                else
                {
                    PerformAjax(arr,users,currentIndex);
                }
            }
        });
    }
    

    【讨论】:

    • 请您解释一下PerformAjax(arr, users, currentIndex); 语句的作用?
    • 因为我们已经编写了一个单独的函数来执行 ajax 调用;我们首先设置currentIndex =0 并调用此函数。现在在那个函数里面; ajax 调用为当前用户执行,在complete: 上,我们通过currentIndex++; 移动到下一个用户,并为下一个用户执行相同的 ajax,直到我们到达用户数组的末尾。我希望这个流程是清晰的。
    • 优秀....按预期工作。谢谢!
    【解决方案4】:

    这是由于异步性质而发生的。在调用 ajax 回调时,i == user.length 已经为真。但在你的情况下,你可以改变:

    if (i == users.length) {
    

    到:

    if (arr.length == users.length) {
    

    如果回调的执行顺序与您启动 ajax 请求的顺序不同,这也可以很好地工作。

    【讨论】:

      【解决方案5】:

      最简单的方法是使用闭包。每当你在一个循环中有一些异步的东西时,都是一样的。

      for (var i .....) {
        async(function() {
          use(i);
        }
      }
      

      在这个伪代码sn-p中,内部函数捕获了i引用的存储位置。循环运行,i 增加到它的最终值,然后异步回调开始被调用,它们都在查找完全相同的位置(而不是值)。

      一般的解决办法是这样的:

      for (var i .....) {
        (function (i) {
          async(function() {
            use(i);
          });
        })(i);
      }
      

      即将循环的全部内容包装在一个自执行函数中。

      这里,外部 i 的值被传递到包装自执行匿名函数中;这个唯一值的位置被异步回调捕获。这样,每个 async 都有自己的值,在调用自执行函数时确定。

      【讨论】:

        【解决方案6】:

        试试下面的代码,它工作正常。

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
        <script>
        var arr = [];
        var users = ["brunofin", "comster404", "ESL_SC2", "OgamingSC2","cretetion","freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
        
        for (i = 0; i < users.length; i++) {
        $.ajax({
          url: "https://api.twitch.tv/kraken/streams/" + users[i],
          async: false,
          success: function(data) {
            arr.push(data);
          },
          error: function(data) {
            arr.push("blank");
          },
          complete: function() {
        
            if (i == (users.length-1)) { 
              console.log(i+'---x--'+users.length); //This seem to print even when the condition isn't true
        
            }
          }
        });
        }
        </script>
        

        请看下面没有循环和 asyncs:false 的代码,测试工作正常。

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
        <script>
        var arr = [];
        var users = ["brunofin", "comster404", "ESL_SC2", "OgamingSC2","cretetion","freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
        var i = 0;
        var getUserData = function(arrUsers) {
           if(i<=arrUsers.length && arrUsers[i] != undefined){
            console.log(arrUsers[i]);
                 $.ajax({
                  url: "https://api.twitch.tv/kraken/streams/" + arrUsers[i][i],
                  async: false,
                  success: function(data) {
                    arr.push(data);
                  },
                  error: function(data) {
                    arr.push("blank");
                  }
                });
            i ++;
            getUserData(users);
           }else{
             console.log(arr); 
           }
        }
        
        getUserData(users);
        </script>
        

        【讨论】:

        • 不设置async:false怎么办?
        【解决方案7】:

        考虑到它们的成功,您可以在不运行另一个请求的情况下调用所有请求:

        var arr = [];
        var users = ["brunofin", "comster404", "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
        
        var runRequests = function(userIndex) {
          if (users.length == userIndex) {
            console.log("runRequests Success", arr);
            return;
          }
        
          var user = users[userIndex];
        
          $.ajax({
            url: "https://api.twitch.tv/kraken/streams/" + user,
            success: function(data) {
              arr.push(data);
            },
            error: function() {
              arr.push({});
              console.error("runRequests Error", "user", arguments);
            },
            complete: function() {
              runRequests(++userIndex);
            }
          });
        };
        
        runRequests(0);
        

        Working demo

        【讨论】:

        • 这行得通,但是即使遇到错误,如何让它继续? (比如我想push'blank'在数组中如果有错误)
        • @OchiFortune 代码已更新。
        • 按我的意愿工作!谢谢
        • @OchiFortune 很好,很高兴为您提供帮助!
        • 不错的一个!把我从精神错乱的边缘救了出来:)
        猜你喜欢
        • 2012-12-11
        • 1970-01-01
        • 1970-01-01
        • 2014-11-26
        • 1970-01-01
        • 2023-03-08
        • 2012-10-18
        • 1970-01-01
        相关资源
        最近更新 更多