Javascript XMLHttpRequest 异步不工作,总是返回状态 0
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7393484/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
XMLHttpRequest asynchronous not working, always returns status 0
提问by Mike D
Here's a sample XMLHttpRequest I cobbled together from w3schools
这是我从 w3schools 拼凑的一个 XMLHttpRequest 示例
<html>
<head>
<script type="text/javascript">
function loadXMLDoc()
{
var T="nothing";
xmlhttp=new XMLHttpRequest();
xmlhttp.overrideMimeType('text/plain'); // don't sc
xmlhttp.onreadystatechange=function()
{
alert ("rdystate: " + xmlhttp.readyState);
alert ("status: " + xmlhttp.status);
alert ("Text: " + xmlhttp.statusText);
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
T = xmlhttp.responseText;
}
}
xmlhttp.open("GET","SBL_PROBES.htm",true);
xmlhttp.send(null);
//T = xmlhttp.responseText;
alert(T);
}
</script>
</head>
<body>
<h2>Using the XMLHttpRequest object</h2>
<div id="myDiv"></div>
<button type="button" onclick="loadXMLDoc()">CHange Content</button>
</body>
</html>
XMLHttpRequest always returns a zero status.
XMLHttpRequest 始终返回零状态。
Nothing shows up in Firefox's error console.
Firefox 的错误控制台中没有显示任何内容。
If I change the request to synchronous one by changing the line
如果我通过更改行将请求更改为同步请求
xmlhttp.open("GET","SBL_PROBES.htm",true);
to
到
xmlhttp.open("GET","SBL_PROBES.htm",false);
and un-comment the line
并取消注释该行
//T = xmlhttp.responseText;
The text of the requested file is returned.
返回请求文件的文本。
The HTM and the file reside in the same directory. If you try this you will need a file SBL_PROBES.htm there also, it's contents are irrelevant.
HTM 和文件位于同一目录中。如果您尝试此操作,您还需要一个文件 SBL_PROBES.htm,它的内容无关紧要。
I'm using Firefox 3.6.22.
我正在使用 Firefox 3.6.22。
Could this be a cross domain problem? If so, why does it work as a synchronous request?
这可能是跨域问题吗?如果是这样,为什么它作为同步请求工作?
回答by evildead
You can use a function inside the if statement. This function is executed when readystate changes to 4.
您可以在 if 语句中使用函数。这个函数在 readystate 变为 4 时执行。
var handleResponse = function (status, response) {
alert(response)
}
var handleStateChange = function () {
switch (xmlhttp.readyState) {
case 0 : // UNINITIALIZED
case 1 : // LOADING
case 2 : // LOADED
case 3 : // INTERACTIVE
break;
case 4 : // COMPLETED
handleResponse(xmlhttp.status, xmlhttp.responseText);
break;
default: alert("error");
}
}
var xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=handleStateChange;
xmlhttp.open("GET","SBL_PROBES.htm",true);
xmlhttp.send(null);
Your old code did a asynchronous call and continued just with the alert Statement. T was empty at this time.
您的旧代码进行了异步调用并继续使用警报语句。此时T是空的。
Ok, I'll explain a little bit how this whole thing works:
好的,我将解释一下整个事情是如何工作的:
First we define two callback functions, which we call later in the request, named handleResponse and handleStateChange.
首先我们定义了两个回调函数,我们稍后会在请求中调用它们,命名为 handleResponse 和 handleStateChange。
Afterwards we create a Object, which represents the XMLHttpRequest
然后我们创建一个对象,它代表 XMLHttpRequest
var xmlhttp=new XMLHttpRequest();
This results in an Object as follows (simplyfied):
这将导致一个对象如下(简化):
XMLHttpRequest { status=0, readyState=0, multipart=false, onreadystatechange=handleEvent()}
With the open(...) function call you set parameters for the request:
使用 open(...) 函数调用,您可以为请求设置参数:
xmlhttp.open("GET","SBL_PROBES.htm",true);
This means, do a asynchronous GET Request to fetch the Page SBL_PROBES.htm Then the send(...) function is called which fires the request itself.
这意味着,执行异步 GET 请求以获取页面 SBL_PROBES.htm 然后调用 send(...) 函数来触发请求本身。
We registered a callback function for the onreadystatechange, as you can imagine, this is actually an eventHandler. Each time the state changes this function is called. (It is the same as if you register a callback function to an onKeyUp Event in a form, this callback is triggered each time your key goes up :) )
我们为onreadystatechange注册了一个回调函数,可以想象,这其实是一个eventHandler。每次状态改变时都会调用这个函数。(就像你在表单中注册一个 onKeyUp 事件的回调函数一样,每次你的键上升时都会触发这个回调:))
The only case which is of interest for your problem is state 4. Therefor the handleRequest callback function is called only in state 4. At this time you Request has actually a result, and further a status. (Status means your webserver returned a status code 200=ok, 404=not found etc.)
唯一对您的问题感兴趣的情况是状态 4。因此,仅在状态 4 中调用 handleRequest 回调函数。此时您的 Request 实际上有一个结果,还有一个状态。(状态意味着您的网络服务器返回了状态代码 200=ok、404=not found 等)
That is not all the magic which is behind the ajax stuff, but should give you a simplified overview, what is actually happening behind the scenes. It is important that you test this on a webserver, do not use file:// for testing.
这并不是 ajax 背后的全部魔法,但应该给你一个简化的概述,幕后实际发生的事情。在网络服务器上测试这一点很重要,不要使用 file:// 进行测试。
If you need more in detail info, just let me know.
如果您需要更多详细信息,请告诉我。
回答by epascarello
Status Zero happens for two reasons.
状态零的发生有两个原因。
- You are running off the file protocol.
- Something is posting back the page when the Ajax request is active.
- 您正在运行文件协议。
- 当 Ajax 请求处于活动状态时,某些东西正在回发页面。
I believe you are seeing #2 here. SO you need to cancel the button click.
我相信你在这里看到了#2。所以你需要取消按钮点击。
<button type="button" onclick="loadXMLDoc(); return false;">CHange Content</button>
In your code above that alert(T) will always say nothingwhen the request is asynchronous.
在上面的代码中,当请求是异步的时,alert(T) 总是什么也不说。
回答by Daniel A. White
Its because async returns before the request returns. Synchronous requests return after the request returns.
这是因为 async 在请求返回之前返回。请求返回后同步请求返回。
Try manipulating your logic in here.
尝试在这里操纵你的逻辑。
xmlhttp.onreadystatechange=function()
{
alert ("rdystate: " + xmlhttp.readyState);
alert ("status: " + xmlhttp.status);
alert ("Text: " + xmlhttp.statusText);
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
T = xmlhttp.responseText;
alert(T);
}
}
回答by Adalars1
I've battled the problem of not getting a result when using asynchronous XMLHttpRequest open statement. Since this question is the first I found when using google, here is how I solved it:
我已经解决了在使用异步 XMLHttpRequest open 语句时没有得到结果的问题。由于这个问题是我在使用 google 时发现的第一个问题,因此我是这样解决的:
If you use a button that is inside a form, make sure it is set to type="submit" and onclick="return myFunction()". And in myFunction(), make sure you return false, nottrue! By returning true from the function, you reload the page and the XML object disappears. If you return false, the XML request gets the time it needs to complete and the onreadystatechange function will be run.
如果您使用表单内的按钮,请确保将其设置为 type="submit" 和 onclick="return myFunction()"。在 myFunction() 中,确保返回 false,而不是true!通过从函数返回 true,您重新加载页面并且 XML 对象消失。如果返回 false,则 XML 请求将获得完成所需的时间,并且将运行 onreadystatechange 函数。
Source: Flask Mailing List
来源:Flask 邮件列表
回答by Stan Truffaut
I have now received the good response to this common problem. The response follow:
我现在已经收到了对这个常见问题的良好回应。回应如下:
This is a very common problem when developing for the web. There's two ways around it.
在为 Web 开发时,这是一个非常常见的问题。有两种方法可以解决。
- The first is to use JSONP, which our API supports when you add a query parameter ("?callback=foo"). This should get you up and running right away and is great for development, but it isn't secure for production use since users get access to your API key.
- The second (which is what we use on Forecast, and is the best method for production) is to set up a proxy server on your own domain which can make requests to Forecast on the user's behalf. This sidesteps the browser's same-origin policy, prevents users from accessing your API key (which can be stored server-side), and also allows you to make use of request caching, if desired. (Our favorite web server, NGINX, supports this out of the box and is really easy to configure. If you need some sample configurations, let us know!)
- 第一种是使用 JSONP,当您添加查询参数 ("?callback=foo") 时,我们的 API 支持它。这应该可以让您立即启动并运行,并且非常适合开发,但由于用户可以访问您的 API 密钥,因此它对于生产使用并不安全。
- 第二种(这是我们在 Forecast 上使用的,也是生产的最佳方法)是在您自己的域上设置代理服务器,它可以代表用户向 Forecast 发出请求。这避开了浏览器的同源策略,防止用户访问您的 API 密钥(可以存储在服务器端),并且还允许您在需要时使用请求缓存。(我们最喜欢的 Web 服务器 NGINX 支持开箱即用,并且非常容易配置。如果您需要一些示例配置,请告诉我们!)