没有jQuery,javascript如何检查多个ajax调用是否已完成,一旦完成,如何执行一段代码?

没有jQuery,javascript如何检查多个ajax调用是否已完成,一旦完成,如何执行一段代码?,javascript,ajax,Javascript,Ajax,我已经知道如何在jQuery中实现这一点(哦,天哪,这很简单),但我只是好奇,在基本javascript中,没有jQuery,如何实现这一点。毕竟,jQuery是javascript,任何可以在其中一种语言中完成的事情都可以在另一种语言中完成(而且一点也不像某些人想象的那么困难!) 请帮我满足我的好奇心!我想了解基本概念~ 一个常见的场景——用户执行多个ajax调用,并且希望仅在两个调用完成后执行一段代码。如何做到这一点 下面是一个常见场景的简单示例。这是我到目前为止尝试过的(但没有成功)。我

我已经知道如何在jQuery中实现这一点(哦,天哪,这很简单),但我只是好奇,在基本javascript中,没有jQuery,如何实现这一点。毕竟,jQuery是javascript,任何可以在其中一种语言中完成的事情都可以在另一种语言中完成(而且一点也不像某些人想象的那么困难!)

请帮我满足我的好奇心!我想了解基本概念~

一个常见的场景——用户执行多个ajax调用,并且希望仅在两个调用完成后执行一段代码。如何做到这一点


下面是一个常见场景的简单示例。这是我到目前为止尝试过的(但没有成功)。我知道它不起作用的原因是,在javascript中,一次只能处理一个ajax调用。那么,在没有jQuery的情况下,正确的方法是什么

//gets result html code, for a settings div inside a log panel
//this page also inserts some info into my database
//it has to run first and finish first before second ajax call, runs
var xmlhttp;
if (window.XMLHttpRequest) xmlhttp=new XMLHttpRequest(); 
else  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); 
xmlhttp.open("POST","/scripts/post_login_panel_actions.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("settings_button_activate=1&display_image_url="+encodeURIComponent(settings_display_picture_url));

//gets result html code, for the login panel inside of which, there is a settings div
//this has to run after, so that it can render the new stuff that was added to my database
var xmlhttp2;
if (window.XMLHttpRequest) xmlhttp2=new XMLHttpRequest(); 
else xmlhttp2=new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp2.open("POST","/scripts/post_login_panel_actions.php",true);
xmlhttp2.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp2.send("settings_refresh_login_panel=1");     

//after both calls have been completed, the new login panel should be rendered
//and then, the new settings-div should be rendered inside of the new login panel
xmlhttp.onreadystatechange=function()  { 
    if (xmlhttp.readyState==4 && xmlhttp.status==200 && xmlhttp2.readyState==4 && xmlhttp2.status==200) {
        document.getElementById("login_panel").innerHTML=xmlhttp2.responseText;
        document.getElementById("login_panel_settings").innerHTML=xmlhttp.responseText;    }    }

阅读答案、评论并尝试编写更多代码后编辑:

lleaff的答案是最好的,真他妈的,它真的是多才多艺,你可以直接复制粘贴它,它会神奇地工作,适用于不同的变量和场景。我认为这是正确的答案

但是这里有一些额外的信息来帮助那些可能无意中发现这个页面的人。。。我自己想出了第二种(更粗糙、更愚蠢的!)控制两者的方法

  • 两个ajax调用的执行顺序(在调用1确实需要在调用2开始之前完成的特殊情况下)
  • 最后一个函数调用仅在两个ajax调用都完成时发生
  • 这里的问题是,javascript的设计并不能让您轻松地检查诸如“变量Y发生变化时触发动作X”之类的内容,因此,对于一些人来说,可能很难找到如何使用这些答案的方法,因为人们会告诉您“保留一个全局变量以跟踪完成的内容”

    每次onreadystatechange函数意识到..就绪状态已更改时,您都可以启动一个检查。我最初实现的问题是,我只检查了一个ajax调用的就绪状态

    一个更粗糙(但更容易理解!)的解决方案,希望这将为查看此主题的人提供更多帮助:

    //Declare your ajax variables~
    var xmlhttp;
    if (window.XMLHttpRequest) xmlhttp=new XMLHttpRequest(); 
    else  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); 
    var xmlhttp2;
    if (window.XMLHttpRequest) xmlhttp2=new XMLHttpRequest(); 
    else xmlhttp2=new ActiveXObject("Microsoft.XMLHTTP");
    
    //Step 1 (first ajax call) code will begin executing here
    xmlhttp.open("POST","/scripts/post_login_panel_actions.php",true);
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.send("settings_button_activate=1&display_image_url="+encodeURIComponent(document.getElementById("settings_display_picture_url").value));
    
    //Step 2 (second ajax call) this function will be called ... later in the code!
    function ajax_call_two() {
        xmlhttp2.open("POST","/scripts/post_login_panel_actions.php",true);
        xmlhttp2.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        xmlhttp2.send("settings_refresh_login_panel=1");
        xmlhttp2.onreadystatechange=function()  { 
            if (xmlhttp2.readyState==4 && xmlhttp2.status==200) {
                //when Step 2 is finished, Step 3 is called.
                stuff_to_do_after_all_ajax_calls_are_finished();    }    }   }  
    
    //Step 3 (stuff_to_do_after_all_ajax_calls_are_finished. literally.) this function will be called ... later in the code!
    function stuff_to_do_after_all_ajax_calls_are_finished() {
        document.getElementById("login_panel").innerHTML=xmlhttp2.responseText;
        document.getElementById("login_panel_settings").innerHTML=xmlhttp.responseText;    } 
    
    //When Step 1 is finished, Step 2 is called.
    xmlhttp.onreadystatechange=function()  { 
        if (xmlhttp.readyState==4 && xmlhttp.status==200) {
            ajax_call_two();    }    } 
    

    只需命名传递给
    xmlhttp.onreadystatechange
    的函数,并将其分配给每个请求的
    onreadystatechange
    属性

    下面是我如何概括这个问题的解决方案:

    function requestsAreComplete(requests) {
        return requests.every(function (request) {
            return request.readyState == 4;
        });
    } 
    
    function unsuccessfulRequests(requests) {
        var unsuccessful = requests.filter(function (request) {
             return request.status != 200;
        };
        return unsuccessful.length ? unsuccessful : null;
    }
    
    function onRequestsComplete(requests, callback) {   
        // Wrap callback into a function that checks for all requests completion     
        function sharedCallback() {
            if (requestsAreComplete(requests)) {
                callback(requests, unsuccessfulRequests(requests));
            }
        }
    
        // Assign the shared callback to each request's `onreadystatechange`
        requests.forEach(function (request) {
            request.onreadystatechange = sharedCallback;
        });
    }
    
    你会这样使用它:

    onRequestsComplete([xmlhttp, xmlhttp2], function(requests, unsuccessful) {
        if (unsuccessful) { return; } // Abort if some requests failed
    
        document.getElementById("login_panel").innerHTML=requests[1].responseText;
        document.getElementById("login_panel_settings").innerHTML=requests[0].responseText;
    });
    

    只需添加一个全局计数器,在发出请求时增加它,在收到响应时减少它,在响应回调中,检查计数器是否减少到0,执行您的一段代码。为了帮助javascript新手和可能正在阅读上述注释的人:“在响应回调中”意味着“检查onreadystatechange内的计数器"~!哇,你每隔几分钟所做的所有编辑都非常好~很抱歉没有马上接受你的答案。我一直在看这一页,但我有点慢,我正在测试这些东西,正如我们所说的那样~你非常有耐心。我很快就会接受答案~只是测试一些东西~呵呵,没问题。是的,我想到了“最好提供一个更通用和可重用的解决方案。如果有什么不起作用,请告诉我。我对你的代码进行了很多测试,它工作得很好,接受了你的答案(但你忘了添加
    );
    最后,出于偶然~!)并使用从你写得很好的回复中学到的知识,编写了我自己的代码解决方案,特别是与我的处境有关的。非常感谢!