如果没有jQuery,javascript如何检查多个ajax调用是否已经完成,一旦完成,就执行一段代码
Without jQuery, how can javascript check that multiple ajax calls have been completed, and once they have, execute a piece of code?
我已经知道如何在jQuery中做到这一点了(哦,天哪,这很容易吗),但我只是好奇在没有jQuery的情况下,如何在基本的javascript中实现这一点。毕竟,jQueryISjavascript,以及任何可以在其中一个中完成的事情,都可以在另一个中进行(而且一点也不像一些人想象的那么困难!)
请帮助满足我的好奇心!我想了解的基本概念
一个常见的场景是,一个用户执行多个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;
});
- 在经过一段时间或满足条件后运行代码
- 下面的一段代码在jquery中会做什么
- Javascript 使用单个函数从另一段代码中取消 POST
- 哪一段代码通常更容易被接受
- JQuery 将一段代码应用于多个元素
- 链接到同一页面上的一段代码
- 是否可以在JavaScript的执行堆栈末尾放置一段代码
- 如果没有jQuery,javascript如何检查多个ajax调用是否已经完成,一旦完成,就执行一段代码
- 在浏览器向服务器发送任何操作URI的请求之前执行一段代码
- 向机器人隐藏一段代码
- 在执行一段代码之前,必须加载两个ExtJS存储
- Node.js:确保一段代码一段接一段地执行
- Javascript跳过一段代码,但在使用调试器时可以正常工作
- 使用if语句关闭html中的一段代码
- 我无法理解一段代码
- 在一段代码中混合使用PHP、Javascript和Ajax
- 我无法让一段代码在jsfiddle之外工作
- 将一段代码从jQuery 1.3.2升级到最新版本
- 如何在$q.all返回之前运行最后一段代码
- 向网页添加一段代码:Chrome 扩展程序