循环中的jQuery.ajax()
如果我在循环中调用jQuery.ajax()
,它会导致当前迭代中的调用覆盖最后一次调用还是为新请求分配了新的XHR对象?
我有一个循环来执行此操作,而从控制台日志我可以看到请求完成200 ok
但是循环中最后一个请求的结果数据由请求success callback
存储为假设。
代码:
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
你需要一个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); }
这样你可以确保每个ajax成功回调中的键始终是正确的。 但除此之外,它应该工作
我使用超时代替ajax做了一个小闭包演示,但原理是一样的:
您需要在ajax请求中使用async:false 。 它将同步发送ajax请求,等待先前的请求完成,然后发送下一个请求。
$.ajax({ type: 'POST', url: 'http://stackoverflow.com', data: data, async: false, success: function(data) { //do something }, error: function(jqXHR) { //do something } });
我相信这里发生的事情与关闭有关。 在这个循环中:
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); }
变量key
实际上是在for循环之外定义的。 所以当你进入回调时,值可能已经改变了。 尝试这样的事情:
var pages = ["a", "b", "c"]; for (var key in pages) { console.log('before: ' + key); (function (thisKey) { setTimeout(function () { console.log('after: ' + thisKey); }, 1000); })(key); }
我遇到了同样的情况,我解决了在新函数中使用ajax调用然后将函数调用到循环中。
它看起来像:
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; } }); }
这就是我总是做ajax循环的方式..
我使用了一个在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") } }