【问题标题】:Javascript: Using asynchronous AJAX synchronouslyJavascript:同步使用异步 AJAX
【发布时间】:2013-10-16 03:35:24
【问题描述】:

首先,我查看了相关的 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 进行标准化。

那太好了。我将需要有条件地更改响应类型,但它不起作用。现在我打算在 something 中包装一个 AJAX 异步请求来模拟同步性。

以下是我的代码使用的通用“发出网络请求”功能,我已经开始适应它以适应我的目的。不幸的是,它并没有像我希望的那样工作。

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秒让全局变量不为空,然后要么返回,要么抛出错误。

问题是我的代码实际上并没有等待 5 秒。相反,它会立即退出,声称它在这样做之前等待了 5 秒。

为了它的价值,我做了一把小提琴。它在那里也不起作用。 http://jsfiddle.net/Z29M5/

非常感谢任何帮助。

【问题讨论】:

  • 为什么要使用同步ajax请求?这不是 ajax 的用途
  • 我无法想象为什么您会需要更改 responseType,而不仅仅是觉得它很方便。字符串总是可以被解码的。
  • 您可能不需要它们同步。只需让他们使用回调一个接一个地触发。
  • 你从不使用responseTypesetTimeout 也是异步的
  • @jimmyweb 我想有人不得不这么说。无视。

标签: javascript ajax asynchronous


【解决方案1】:

你做不到。坚持异步请求。回调地狱很烂,但这就是你在没有语言支持的事件驱动系统中得到的。

目前根本没有办法在浏览器中用纯 JavaScript 模拟同步代码。

如果您可以严格限制您支持的浏览器集(目前几乎只是 Firefox AFAIK),您可以使用生成器获得同步的外观代码。 p>

还有一些语言可以编译成 JS 并支持看起来同步的代码。我能想到的一个例子(几年前)是这样的:https://github.com/maxtaco/tamejs

【讨论】:

  • 回调地狱确实很糟糕,这就是我试图避免的。我开始觉得这就是我要坚持的事情。
【解决方案2】:

首先,尽管很痛苦,但异步使用异步代码是可行的方法。它采用不同的方法,仅此而已。

其次,对于您的具体问题,这就是您的“延迟”循环正在做的事情:

For twenty iterations
  if we've had a response, break
  set a timeout for 250ms
go round again

(整个 for 循环立即完成所有 20 次迭代。你不会有任何响应)

。 . . 250 毫秒后

执行第一个setTimeout回调,即nop

执行第二个...

除了将您的处理代码放在 AJAX 回调中之外,我想不出一种快速的方法来解决这个问题,无论如何,这应该是异步代码的位置。

【讨论】:

    【解决方案3】:

    为什么不创建一个请求数组,然后在收到上一个 ajax 调用的响应时将它们逐个弹出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      • 2014-03-29
      • 1970-01-01
      • 2010-10-25
      • 2023-04-01
      • 2012-02-25
      • 1970-01-01
      相关资源
      最近更新 更多