I have a custom webserver, and some content that has been working for probably 18 months or more. The code has not been touched in all that time. But, I now find one feature, which depends on Ajax, is no longer working. The problem is on the browser side. Sadly, the Ajax code was found using Google, and even when I customized it, I didn't really understand it, but it has worked until some time in the last 6 months or so. Now that it's no longer working, I'm kinda lost....
What the code does is pretty simple. My HTML form is a tab control. One of the tabs is used for displaying error messages. The Ajax code sends a GET request for "\ATCStatus.txt" roughly once per second. The server responds with:
HTTP/1.1
Server: arduino
Content-Type: text/plain
#ATCErrorFlag#
where #ATCErrorFlag# gets replaced with wither "true" or "false". If "false" is returned, nothing happens. If "true" is returned, then the Ajax code sends a request for "\ATCErrorPage.htm", which switches to the error tab, and displays the error message.
The server receives the requests, processes them, and sends the correct response, but Ajax code acts like no response was ever received, and I can't figure out why.
Anyone here know enough Ajax to have a clue?
Here is the Ajax code:
setInterval(PollATCError, 1000);
function PollATCError()
{
var xhr;
if (window.XMLHttpRequest)
xhr = new XMLHttpRequest();
else if (window.ActiveXObject)
xhr = new ActiveXObject("Msxml2.XMLHTTP");
else
throw new Error("Ajax is not supported by your browser");
xhr.onreadystatechange = function()
{
if (xhr.readyState == 4 && xhr.status == 200)
{
clearTimeout(xhrTimeout);
var response = xhr.responseText;
if (response == "false") {
// Do nothing
} else if (response == "true") {
// else, throw up Error Page
window.location.replace('ATCErrorPage.htm');
//document.getElementById("tab4event").click();
}
}
}
xhr.open('GET', 'ATCStatus.txt', true);
xhr.send(null);
var xhrTimeout = setTimeout("ajaxTimeout();", 900);
function ajaxTimeout()
{
xhr.abort();
// Note that at this point you could try to send a notification to the
// server that things failed, using the same xhr object.
}
}
What seems especially odd is that I don't ever seem to get any state change notifications. If I make the first line of the state change handler an alert(), the alert never comes up. The request does go to the server, the correct response is sent back to the client, but seems to never be seen by the XMLHttpRequest object. Even the 900mSec timeout never happens.
This used to work very nicely! What has gone wrong?? How can I get to the bottom of this?
Regards,
Ray L.
Related
In my tests Chrome (and I guess as any other webkit browser probably) is UNABLE to perform an AJAX request BEFORE leaving a page.
Imagine for instance, that you need to clean up something on the server because the user clicked on some link or left the page.
First thing I noticed is that window.onunload DOES NOT work anyhow on Chrome (Webkit?)
Once you are using window.onbeforeunload MAKE SURE you DON'T put in the the body like this: Cause it is ignored. YOU HAVE TO do window.onbeforeunload=function() {...} to make sure the binding is done (or use jquery or protoype libs for this)
WITHIN your onbeforeunload code a ASYNCHRONOUS Ajax like this WON'T work either:
var req = new XMLHttpRequest();
req.open("GET", "dosomething.page");
req.send(null);
(although this will WORK in Firefox)
It will work if ONLY if the request is made SYNCHRONOUS like this:
var req = new XMLHttpRequest();
req.open("GET", "dosomething.page",false);
req.send(null);
Although keep in mind that synchronous can cause the browser to hang for 2minutes if the server does NOT reply.
Also Firefox DOES NOT seem to work with onunload.
So in the end YOU have to provide with a different code path for each browser or browser family.
I haven't been able to test IE properly on this.
Does anyone know?
Is IE more like Chrome or FF in this?
or is it different to both as well?
IE seems to work just like Firefox (Gecko) in this particular case:
With this code you can make it work for WebKit, Firefox and IE:
// Browser detection
var Browser={
IE: !!(window.attachEvent && !window.opera),
Opera: !!window.opera,
WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
};
// Ensures the Ajax Get is performed... Asynchronously if possible
// or Synchronously in WebKit Browsers (otherwise it'll most probably fail)
function ensureAJAXGet(url, args) {
var async=!Browser.WebKit;
var finalUrl=url;
var sep="";
for (var key in args) {
sep=(sep=="?")?"&":"?";
finalUrl=finalUrl+sep+encodeURIComponent(key)+"="+encodeURIComponent(args[key]);
}
var req = new XMLHttpRequest();
req.open("GET", finalUrl,async);
req.send();
return req;
}
// Sets up an unload function for all browsers to work (onunload or onbeforeunload)
function onUnload(func) {
if(Browser.WebKit) {
window.onbeforeunload=func;
} else {
window.onunload=func;
}
}
A test html could be this:
var browser="?"
if (Browser.IE) {
browser="IE";
} else if (Browser.Opera) {
browser="Opera";
} else if (Browser.WebKit) {
browser="WebKit";
} else if (Browser.Gecko) {
browser="Gecko";
} else if (Browser.MobileSafari) {
browser="MobileSafari";
}
function unload() {
ensureAJAXGet("testajax.jsp", {"browser": browser});
}
onUnload(function() { unload(); });
That is:
To do something onunload you call onUnload() instead of directly using either window.onload or window.onunload. This ensures that the proper event is used (onbeforeunload in WebKit and onunload on the rest)
To sent some GET Ajax on an unload function use ensureAjaxGet() that will be asynchronous AJAX when possible and synchronous when needed (WebKit)
While designing a error handling mechanism for AJAX script on my website, I found that the only status code that was returned, by the server, in the event of a error was 0 (or "undefined"). Even when I intentionally created a 404 error by requesting a non-existent file, the only error code that was returned by the server was 0. I believe that this problem is caused by my web-host's server (www.000webhost.com) when it redirects 404 errors to http://error404.000webhost.com/? however, I need to find a way to get a proper error code from the server's response in order to deliver feedback to the user on what went wrong... So my question is: how do I make the server return the proper status code, or if that is not the problem: what is wrong with my code?
var xmlhttp;
if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else { // code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
alert(xmlhttp.status); //this alert box shows 200 normally, but during a error only shows 0
if (xmlhttp.status==200) { // 200 = OK, process result
//stuff for processing the result (when there is no error)
}
else { // error handling (creates a jgrowl notification showing the status code)
$('#jGrowl-container').jGrowl('AJAX Error Code: ' + xmlhttp.status', {sticky: true, theme: 'error'});
}
}
}
xmlhttp.open("POST", "process.php", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("&s="+ScoutID + "&pw="+pword + "&rt="+RequestType + RequestText);
}
There could be different reasons why you are NOT getting proper http-status codes in response.
Check with your hosting provider whether they are handling or have customized the web server for this. You can check it in their control panel or ask their helpdesk.
Your server is redirecting in case of 404 which may not let the browser track it as 404 but instead a 302 or 303 (redirection). Few hosting companies do that.
Also I noticed that you are using jQuery already so why not use it for your ajax calls as well. It works well. You can check it out at http://api.jquery.com/category/ajax/
I'm trying to solve how to do Streaming for IE and long-polling without folding the server. Here what I had in mind.
I 'll have a servlet called : TimeServlet.
in doGet or doPost() .. I'll suspend the request and send the time at each seconds.
....
suspend()
while(!stopped){
request.writeln(new Date().toString());
}
or with a Scheduler and Runnable, but you get the point.
On the client in javascript I'll create a ajax connection.
My big questions are :
1 - How do I do streaming with IE ? with Firefox and Chrome, I read the data when readyState==3, but in IE, the data is only available on readyState==4.
2 - How can I do long-polling in this example ? Long-polling block until the server had data to push, but in this example, the server will always have something to push, so the client will do something like while(true) and flood the server. I suppose that I have to do something like that
ajax.push(null) ... on readyState==4 -> read ... after that setTimeout(resendRequest, 1); //1 sec ?
there is someone that have a sample like that ?
my code works fine for FF and Chrome, but now I'm looking for IE and Opera.
EDIT
I found that I could use XDomainRequest in IE for streaming. You have to have that in your server code :
response.setHeader("Access-Control-Allow-Origin","*");
I won't answer this question yet, because I don't know how to detect that the connection is completed.
with Ajax, it was easy.. ReadyState==4. but I don't know for XDomainRequest.
I need to be able to trigger some javascript callback when the connection is closed. Any ideas ?
I found how to detect the close event. You have to use the onload method.
So the code will look like that
var ajaxRequest = new XDomainRequest();
ajaxRequest.onload = function() {
//alert("[XDR-onload]. responseText: " + ajaxRequest.responseText + "");
};
ajaxRequest.onerror = function() { alert("[XDR-onerror] Fatal Error."); };
ajaxRequest.ontimeout = function() {
alert("[XDR-ontimeout] Timeout Error.");
};
ajaxRequest.onprogress = function() {
//alert("[XDR-onprogress] responseText so far: " + ajaxRequest.responseText + "");
};
and don't forget to add the Header in the response (server's side)
response.setHeader("Access-Control-Allow-Origin","*");
I am new to this site and had been successfully using the "HTML5" Cross-origin resource sharing (CORS) to POST data to my server. I just recently tried to include GETs in that as we are trying to have all of our communications be non-reliant on a JavaScript library. In doing so I have run into an odd issue that seems somewhat fixable for Firefox but is still misbehaving in all the WebKit browsers. Essentially anything that returns a status of <200 or >300 is just coming in as a status of 0. This makes it next to impossible to do error handling.
For Firefox, I am able to put a random string on the end of the request to prevent it from being cached; thereby fixing the 304s at least. This however does not work at all for me in Chrome/Safari. Here is a sample of my code:
xhr_request: function(type,url, data, callbacks, form){
var form = (typeof(form)!=="undefined")?form:null;
var xhr = new XMLHttpRequest();
var response;
data = com.ticommunity.obj_to_string(data);
xhr.open(type, url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("X-TxId", com.ticommunity.keyGen());
xhr.withCredentials = true;
xhr.send(data);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
response = xhr.responseText;
com.ticommunity.comm.request_callback(response, callbacks, form);
}else{`//****this is where the 0 Status keeps coming up***`
response = xhr.status;
com.ticommunity.comm.request_callback(response, callbacks, form);
}
}
}
}
Has anyone else run into something similar and come up with a work-around? Am I just doing something stupid on my end? Any help is greatly appreciated.
EDIT: I realized the 0 is what is supposed to happen per the spec, but I REALLY need to be able to trap for these situations and do some other handling.
I haven't seen this issue specifically, but I wonder if you'd have better luck using a different xhr event, such as xhr.onload. You can trust onload to fire on successful responses, so there's no need to check xhr.status. Here's a complete list of events if you need to trap on something else:
http://www.w3.org/TR/XMLHttpRequest2/#events
I have a pretty simple AJAX and PHP code. While calling the PHP through the AJAX it receives the response code as 0. The PHP code is successfully run, but I can't get the response. What does this status '0' denote and how can I solve this?
function confirmUser(id)
{
xmlhttp=GetXmlHttpObject();
regid = id;
if (xmlhttp==null) {
alert ("Browser does not support HTTP Request");
return;
}
var url="confirm.php";
url=url+"?id="+id;
url=url+"&a=confirm";
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
$("#txtHint" + regid).text("Awaiting confirmation");
} else {
alert (xmlhttp.status); //this shows '0'
}
};
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
Well, this is the javascript I used. Pardon me if I should've added anything more than this. Also tell me what I missed.
I appreciate your help
GetXmlHttpObject function:
function GetXmlHttpObject()
{
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject) {
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
When working with XMLHttpRequests in the past, I've found that status 0 is usually returned for locally processed files. When I saw this question, I had a bit of a hunt around and found a confirmation of this at the following pages:
XMLHttpRequest - Why Status 0, and StatusText Unknown occur
https://developer.mozilla.org/En/Using_XMLHttpRequest#section_3
Here are the readyState codes for you.
0. Uninitialized
1. Set up, but not sent
2. Sent
3. In flight
4. Complete
(Source: http://www.stevefenton.co.uk/Content/Blog/Date/201004/Blog/AJAX-Ready-State-Codes/)
Do you get stuck constantly on a readyState of 0? If so, it means your request hasn't been sent, although I can see a line of code in your example "xmlhttp.send(null)"...
I would predict that you'll get a 0 before you call send, but after that a different status code. What happens if you wait a bit?
I know people may not want to hear it, but this is exactly what JS frameworks are for. Why mess with all of the various browser inclinations and disasters that are custom AJAX calls when you can just do a simple AJAX call through jQuery.
Basically, you are reinventing the wheel, and for no reason. Have your php return JSON data, and embed a variable in with the success code if you need to test for that.
<script src="jquery.js"></script>
<script>
$.get("myphp.php", { id : "yes", blah : "stuff" }, function(data) {
if (data.success == 1) {
alert("got data");
} else {
alert("didn't get data");
}
},"json");
</script>
Boom, you now have cross-browser AJAX.
This can happen if you're requesting an HTTPS resource and the handshake fails (for example an invalid certificate). In particular, if you're using the XML request object from outside a browser, the error may not be obvious.