循环中的 jQuery.ajax()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17981631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 20:19:07  来源:igfitidea点击:

jQuery.ajax() inside a loop

ajaxjqueryxmlhttprequest

提问by MTVS

If I call jQuery.ajax()inside a loop, would it cause the call in current iteration overwrite the last call or a new XHR object is assigned for the new request?

如果我jQuery.ajax()在循环内调用,是否会导致当前迭代中的调用覆盖上次调用或为新请求分配新的 XHR 对象?

I have a loop that do this, while from console log I can see requests done 200 okbut just the result data of the last request in the loop is stored by the request success callbackas supposed .

我有一个循环来执行此操作,而从控制台日志中我可以看到请求已完成,200 ok但循环中最后一个请求的结果数据仅success callback按假设由请求存储。

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

回答by Andy

You'll need a closure for key:

你需要一个闭包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);
}

that way you make sure that key is always the correct on in each ajax success callback. but other than that it should work

这样您就可以确保在每个 ajax 成功回调中该键始终是正确的。但除此之外它应该可以工作

i made a small closure demonstration using timeout instead of ajax but the principle is the same:

我使用 timeout 而不是 ajax 做了一个小的闭包演示,但原理是一样的:

http://jsfiddle.net/KS6q5/

http://jsfiddle.net/KS6q5/

回答by Yura Zabolotny

You need to use async:falsein you ajax request. It will send the ajax request synchronously waiting for the previous request to finish and then sending the next request.

您需要在 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
    }
});

回答by Jason P

I believe what's happening here has to do with 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 variable keyis actually defined outside the for loop. So by the time you get to the callbacks, the value has probably changed. Try something like this instead:

该变量key实际上是在 for 循环之外定义的。因此,当您进行回调时,该值可能已更改。试试这样的:

http://jsfiddle.net/VHWvs/

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

回答by JPRLCol

I was facing the same situation, I solved using the ajax call inside a new function then invoke the function into the loop.

我面临同样的情况,我在新函数中使用 ajax 调用解决了问题,然后将该函数调用到循环中。

It would looks like:

它看起来像:

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

回答by gezzuzz

This is how I always do a ajax loop..

这就是我总是做一个ajax循环的方式..

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

我使用一个递归函数,该函数在 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")
    }
}