首先,我查看了相关的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/
非常感谢任何帮助。
答案 0 :(得分:2)
你不能这样做。坚持异步请求。回调地狱很糟糕,但这是你在没有语言支持的事件驱动系统中得到的。
目前在浏览器中根本无法在纯JavaScript中模拟同步代码。
如果您可以严格限制支持的浏览器集(几乎只是 Firefox AFAIK),您可以使用生成器获得同步查找代码。
还有一些语言可以编译成JS并支持同步代码。我能想到的一个例子(几年前)是:https://github.com/maxtaco/tamejs
答案 1 :(得分:1)
首先,对于所有的痛苦,异步使用异步代码是要走的路。它需要一种不同的方法,就是这样。
其次,对于您的具体问题,这就是您的'延迟'循环正在做的事情:
For twenty iterations
if we've had a response, break
set a timeout for 250ms
go round again
(整个for循环立即完成所有20次迭代。你将没有响应)
。 。 。 250ms之后
执行第一个setTimeout
回调,即nop
执行第二次......
除了将处理代码放在AJAX回调中之外,我无法想到一个快速解决此问题的方法,无论如何,这应该是异步代码的位置。
答案 2 :(得分:0)
为什么不创建一个请求数组,只要在收到上一个ajax调用的响应时就将它们逐个弹出。