How to call an ajax function in a for loop [duplic

2020-06-05 06:03发布

I'm new to ajax and JavaScript. What am trying to do is to call an ajax function several times to fetch certain data from a resource and then "push" all of the data into an array so that I can use it later on in the code. Here is my code.

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
            }
        }
    });
}

The problem with the code is that, it prints to the console even when i isn't equal to users.length

My question is; how do I make certain that it waits until i == users.length is true before it prints to the console? Please keep in mind that I still desire the process to be asynchronous.

7条回答
霸刀☆藐视天下
2楼-- · 2020-06-05 06:09

you can try by calling ajax with async false as below

$.ajax({
        type: "GET",
        url: remote_url,
        async: false,
        success : function(data) {
            remote = data;
        }
    });
查看更多
欢心
3楼-- · 2020-06-05 06:15

This happens because of the asynchronous nature. By the time the ajax callbacks are called, i == user.length is already true. But in your case you can just change:

if (i == users.length) {

to:

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

This will also work nice if the callbacks are not executed in the same order as you initiated the ajax requests.

查看更多
淡お忘
4楼-- · 2020-06-05 06:15

Can you try below code:

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);
            }
        }
    });
}
查看更多
我只想做你的唯一
5楼-- · 2020-06-05 06:20

Try Below code it's working fine.

<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>

Please have look below code wihout loop and asyns:false, tested working fine.

<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>
查看更多
Fickle 薄情
6楼-- · 2020-06-05 06:25

The easiest way is to use a closure. Whenever you have something asynchronous in a loop, it is the same thing.

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

In this pseudocode snippet, the inner function captures the storage location referenced by i. The loop runs, the i increments to its final value, and then the async callbacks start getting called, all of them looking up the exact same location (not value).

The general solution is this:

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

i.e. wrap the whole contents of your loop in an self-executing function.

Here, the value of outer i gets passed into the wrapping self-executing anonymous function; this unique value's location gets captured by the async callback. In this way, each async gets its own value, determined at the moment the self-executing function is invoked.

查看更多
家丑人穷心不美
7楼-- · 2020-06-05 06:33

Here is how you can call all requests considering their success without running an request over another:

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

查看更多
登录 后发表回答