JQuery.ajax () inside the loop

If I call jQuery.ajax() inside the loop, will the call in the current iteration cause the last call to be overwritten, or will a new XHR object be assigned to the new request?

I have a loop that does this, while from the console log I can see 200 ok completed requests, but only the result data of the last request in the loop is saved by the success callback request as expected.

the code:

 var Ajax = { pages: {}, current_request: null, prefetch: function () { currentPath = location.pathname.substr(1); if(this.pages[currentPath]) { var current = this.pages[currentPath]; delete this.pages[currentPath]; current['name']=currentPath; current['title']=$("title").text().replace(' - '.SITE_NAME, ''); current['meta_description']=$("meta[name=description]").attr('content'); current['meta_keywords']=$("meta[name=keywords]").attr('content'); } var _Ajax = this; //the loop in question ***** for(var key in this.pages) { $.ajax({ method: 'get', url:'http://'+location.hostname+'/'+key, success: function(data) { _Ajax.pages[key] = data; } }); console.debug(this.pages); } if(current) { this.pages[currentPath] = current; } } };//Ajax Obj for(var i in pages) { Ajax.pages[pages[i]]={}; } $(function() { Ajax.prefetch(); });//doc ready 
+7
jquery ajax
source share
5 answers

You will need a closure for key :

 for(var k in this.pages){ (function(key){ $.ajax({ method: 'get', url:'http://'+location.hostname+'/'+key, success: function(data) { _Ajax.pages[key] = data; } }); console.debug(this.pages); })(k); } 

this way you make sure that the key is always valid in every ajax callback. but other than that it should work

I made a small demo of closing using a timeout instead of ajax, but the principle is the same:

http://jsfiddle.net/KS6q5/

+24
source share

You need to use async: false in the ajax request. It will send an ajax request synchronously, waiting for the previous request to complete, and then send the next request.

 $.ajax({ type: 'POST', url: 'http://stackoverflow.com', data: data, async: false, success: function(data) { //do something }, error: function(jqXHR) { //do something } }); 
+7
source share

I believe that what is happening here is connected with the closure. In this loop:

  for(var key in this.pages) { $.ajax({ method: 'get', url:'http://'+location.hostname+'/'+key, success: function(data) { _Ajax.pages[key] = data; } }); console.debug(this.pages); } 

The key variable is actually defined outside the for loop. So, by the time you get to the callbacks, the value has probably changed. Try something like this:

http://jsfiddle.net/VHWvs/

 var pages = ["a", "b", "c"]; for (var key in pages) { console.log('before: ' + key); (function (thisKey) { setTimeout(function () { console.log('after: ' + thisKey); }, 1000); })(key); } 
+6
source share

I faced the same situation, I decided to use the ajax call inside the new function, and then call the function in a loop.

It will look like this:

 function a(){ for(var key in this.pages) { var paramsOut [] = ... myAjaxCall(key,paramsOut); ....... } } function myAjaxCall(paramsIn,paramsOut) { $.ajax({ method: 'get', url:'http://'+location.hostname+'/'+paramsIn[0], success: function(data) { paramsOut[key] = data; } }); } 
+3
source share

This is how I always do an ajax loop.

I use a recursive function that is called after xhr.readyState == 4

 i = 0 process() function process() { if (i < 10) { url = "http://some.." + i var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { alert(xhr.responseText) i++ process() } } xhr.send(); } else { alert("done") } } 
+2
source share

All Articles