Javascript:同步使用异步 AJAX
Javascript: Using asynchronous AJAX synchronously
首先,我查看了相关的SO问题,并没有找到太多合适的答案,所以这里是:
我一直在开发一个HTML/Javascript页面,它充当后端服务器的UI。我在完成它方面取得了一些不错的进展,同时在 AJAX(又名 var xmlhttp = new XMLHttpRequest(); xmlhttp.open(type, action, false);
(中使用同步调用,但现在发现 Mozilla 显然不喜欢同步请求,因此弃用了一些急需的功能。
引用 https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest:
注意:从 Gecko 11.0(Firefox 11.0/Thunderbird 11.0/SeaMonkey 2.8(以及 WebKit build 528 开始,这些浏览器不再允许您在执行同步请求时使用 responseType 属性。尝试这样做会引发NS_ERROR_DOM_INVALID_ACCESS_ERR异常。此更改已向 W3C 提出以进行标准化。
所以那太好了。我需要有条件地更改响应类型,但它不起作用。现在,我打算将 AJAX 异步请求包装在模拟同步性的东西中。
以下是我的代码使用的一个通用的"make web request"函数,我已经开始适应它以适合我的目的。不幸的是,它并没有像我希望的那样工作。
var webResponse = null;
function webCall(action, type, xmlBodyString) {
console.log("In webCall with " + type + ": " + action);
webResponse = null;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState == 4)
{
if (xmlhttp.status == 200) {
webResponse = xmlhttp.responseXML;
} else {
var statusTxt = xmlhttp.statusText;
if (statusTxt == null || statusTxt.length == 0) {
statusTxt = "An Unknown Error Occurred";
}
throw "ERROR " + xmlhttp.status + ":" + statusTxt;
}
}
}
xmlhttp.open(type, action, true);
if (xmlBodyString == null) {
xmlhttp.send();
} else {
xmlhttp.setRequestHeader("Content-Type", "text/xml");
xmlhttp.send(xmlBodyString);
}
for (var i = 0; i < 20; i++) {
if (webResponse != null) {
break;
}
window.setTimeout(nop, 250);
}
if (webResponse == null) {
throw "Waited 5 seconds for a response, and didn't get one.";
}
console.log("Responding with " + webResponse);
return webResponse;
}
function nop() {
}
所以,我认为这很简单。创建一个全局变量(回想起来,它可能甚至不必是全局的,但现在是 w/e(,设置 onreadystatechange 以在准备就绪后为其赋值,发出我的异步请求,最多等待 5 秒,让全局变量不为 null,然后返回它,或者抛出错误。
问题是我这里的代码实际上并没有等待 5 秒。相反,它会立即退出,声称在这样做之前它等待了 5 秒。
我做了一个小提琴,为了它的价值。它在那里也不起作用。http://jsfiddle.net/Z29M5/
任何帮助将不胜感激。
你不能这样做。坚持异步请求。回调地狱很糟糕,但这就是你在没有语言支持的事件驱动系统中得到的。
目前根本没有办法在浏览器中模拟纯JavaScript的同步代码。
如果你可以严格限制你支持的浏览器集(目前几乎只是 Firefox AFAIK(,你可以通过使用生成器获得同步查看的代码。
还有一些语言可以编译成JS并支持同步代码。我能想到的一个例子(几年前(是这样的:https://github.com/maxtaco/tamejs
首先,对于所有的痛苦,异步使用异步代码是要走的路。它采取了不同的方法,仅此而已。
其次,对于您的具体问题,这就是您的"延迟"循环正在做的事情:
For twenty iterations
if we've had a response, break
set a timeout for 250ms
go round again
(整个 for 循环立即完成所有 20 次迭代。你不会有回应(
. . . 250毫秒后
执行第一个setTimeout
回调,nop
执行第二个...
我想不出解决这个问题的快速方法,除了将您的处理代码放在 AJAX 回调中,无论如何它应该是异步代码的地方。
为什么不创建一个请求数组,并在收到上一个 ajax 调用的响应时逐个弹出它们。
- 调用后不异步Ajax忽略函数
- 在异步AJAX调用完成后,通过变量运行函数
- 将 jQuery UI 日期选择器与异步 AJAX 请求一起使用
- AngularJS:多个异步AJAX调用
- Qt-WebView是否支持包含异步Ajax的网页
- 同步/异步AJAX函数的模式
- 单击链接时执行异步AJAX调用,然后跟随该链接
- Javascript异步AJAX和递归排序
- 记住使用异步 Ajax 获取数据的 Javascript 函数
- 如何将异步 ajax 响应捕获到变量中
- 异步 ajax 调用阻止 UI
- JavaScript 中异步 Ajax 调用的测试结果
- 使用异步/ajax 时保持不变的粘性页脚
- 使用 ko.mapping.fromJS 更新异步 ajax 调用后可观察的淘汰表
- 使用异步 AJAX 或 jQuery 完全重新加载页面
- 而循环与jQuery异步AJAX调用
- Javascript:同步使用异步 AJAX
- JQuery/Ajax:如何将多个 ajaxes 组合成一个具有响应的异步 ajax
- 双异步 AJAX 函数
- jQuery 等到异步 ajax 调用完成