Problem: XMLHttpRequest - handle server connection lost - javascript

How do I handle the scenario where I making a synchronous request to the server using XMLHttpRequest and the server is not available?
xmlhttp.open("POST","Page.aspx",false);
xmlhttp.send(null);
Right now this scenario results into a JavaScript error:
"The system cannot locate the resource specified"

Ok I resolved it by using try...catch around xmlhttprequest.send
:
xmlhttp.open("POST","Page.aspx",false);
try
{
xmlhttp.send(null);
}
catch(e)
{
alert('there was a problem communicating with the server');
}

Try the timeout property.
xmlHTTP.TimeOut= 2000

You don't check for properly returned status. By the code you gave you are doing a GET request.
To properly check the status of your request, you must create an event handler for the onreadystatechange event and then inside it check if the readyState property is equal 4 and then inside the method if the status is 200.
You can find a detailed explanation here :Ajax Tutorial by Mozilla
xmlhttp.onreadystatechange=function()
xmlhttp.open("GET","Page.aspx",false);
{
if (xmlhttp.readyState==4)
{
if (xmlhttp.status==200)
{
//Ajax handling logic
}
}
}
xmlhttp.send(null);

Related

XHR throws timeout error and does not execute onTimeout event

I am coding a native JavaScript application in which I make simultaneous AJAX requests to multiple unique servers every minute. When a server is offline, I intended my program to handle this through the function registered to the XHR.ontimeout event.
Below is a quick JS sample I wrote to demonstrate my problem. Monitor the console and you will see only sometimes requests to an offline address trigger the ontimeout event. Other times ERR_CONNECTION_TIMED_OUT occurs. I would like to have a timeout handler that executes every time I call my function and the server is offline.
<!DOCTYPE html>
<html>
<TITLE>Timeout Error Demo</TITLE>
<body>
<script>
var i=0;
var xhr;
function main(){
console.log('Main run #'+i);
i++;
xhr=new XMLHttpRequest();
xhr.open("GET", "http://1.1.1.1", true); //this address is always offline
xhr.timeout=2000;
xhr.ontimeout=function(){
console.log("timed out");
}
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200){
console.log("done");
}
}
xhr.send(null);
setTimeout(main,5000);
}
main();
</script>
</body>
</html>
As i see it the core of the problem here is that you misunderstand how the ontimeout event works. So i will try to explain how the browser works with ontimeout and what the difference is with onerror.
ontimeout
The ontimeout event will to thrown when a request is made to the server and that request get succesfully through to the server. Then if the server takes a long time to response the timeout event will get thrown by the HTTPRequest.
Ex:
Client side
xhr.timeout = 2000;
xhr.send();
xhr.open("GET", /somecontroller/IAmAReallySlowEndpoint, true);
xhr.ontimeout = function() {
console.log("I get called because the server was to slow to response on a succesfull request");
}
Server side endpoint (C#)
public bool IAmAReallySlowEndpoint()
{
Thread.Sleep(4000);
return true;
}
you call a server side endpoint which does not answer within 2 seconds then the ontimeout event will get thrown.
onerror
The onerror event will throw if an error in the http request happens which is the case in your example. You want to call an url that is down. Calling an url that is down will throw an error and thereby the onerror event is called.
So when you write that it works when do you:
xhr.ontimeout = xhr.onerror
You are just passing the onerror event to the ontimeout.
So to solve your problem with doing stuff if one of the endpoints you are requesting is down you should implement some retry logic kinda like you already have with a setTimeout() but deciding if the server is down or not should be based on numbers of failed request to the server instead of the ontimeout.
It's .ontimeout, not .onTimeout. Or .addEventListener("timeout", …).

XHR status 0, readystate 1 on localhost

Working on my own project. I'm sending an XMLHttpRequest to localhost from Firefox 44 to XAMPP. I'm receiving a status of 0 and a readystate of 1. Here's the code in question.
function sendReq(php,segment){
alert("sendreq called ");
//we out here getting 0 statuses. check out cwd, check out what php value is,
xhr.open("POST", php, true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.onreadystatechange = getData(segment);
xhr.send();
}
//callback function for ajax request.
function getData(div){
if ((xhr.readyState == 4) && (xhr.status == 200))
{
var serverResponse = xhr.responseText;
div.innerHTML = serverResponse;
}else{
div.innerHTML = "<p>loading!</p> ready state: " + xhr.readyState +"</br> status: "+ xhr.status;
}
}
I've read elsewhere the RS:1 / S:0 XHR properties indicate a unsuccessful cross domain request, but this is all occuring on localhost, with the files all in the same directory, and when inspecting the XHR response in Firebug, the return text is in there.
I've built a login to this page almost identical code and it works, its only pointing to a different .php file. Comparing the two and googling around are not enlightening me. So any advice is welcome. Thanks!
You're executing the getData() function once, on pageload, and returning undefined to the onreadystatechange handler, as that's what happens when you add the parentheses.
It has to be either
xhr.onreadystatechange = getData;
Note the lack of parentheses, or if you have to pass arguments
onreadystatechange = function() {
getData(segment);
}

Load error is not captured by try catch block

I have a code like:
try{
...
} catch(error){
...
};
In try block, there is a function call that makes a request to a server. When there is no resource on the server, an error is raised (as I can see in Google Chrome's developers tool):
Failed to load resource: the server responded with a status of 404 (Not Found)
and I am trying to catch it in the catch block, but the error is not captured.
Is it a feature of JavaScript that load error is not captured by try catch block?
Typically, when requesting information from a server (for instance, via ajax, by setting the src of an img element, etc.), you don't get an exception, but you do get an error event or callback, not least because the code doing the request finishes before the request does, so it's impossible to throw an exception at that point. Since you haven't shown how you're requesting the information, it's impossible to be more specific, but this is why you're not getting an exception.
For instance, with an ajax request, if there's an error you see the ajax request complete but with the statusCode of the XMLHttpRequest object being an error status code, rather than 200. E.g.:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// The request is complete; did it work?
if (xhr.statusCode >= 200 && xhr.statusCode < 300) {
// Yes
}
else {
// No, got a code outside the 2xx range
}
}
};
xhr.open("GET", "/your/url/here", true);
xhr.send();

Get all xhr request

I'm trying to get all xhr status 200 and their information when completed. It is possible to get them together in some way or I would have to keep a reference to each of them when i send?
You can use jQuery's ajaxComplete,
$(document).ajaxComplete(function(event, xhr, settings) {
if (xhr.status === 200) {
//rest of the handler
}
});
This will ensure all your ajax responses will hit this method when they're complete, an extra check will be required for the status of the response.
if you are using asp.net then you can add Application_EndRequest method in your global.asax file and check the response.

facebook graph api ajax XMLHttpRequest - Null result?

Summary: Keep getting null response despite public data and setting callback to enable cross domain JSON. Please help!
A similar question has been answered here
Using the new facebook graph api, ajax calls returns null (empty)
but I'm not using jquery and have tried to adapt my code to reflect that answer.
I'm trying to use a simple example to test a simple xmlhttprequest handler. I have this link in my page:
<a href='javascript:loadXMLDoc(\"https://graph.facebook.com/btaylor?callback=methodname\",\"\")'>AJAX LINK</a>
The callback=methodname parameter is to enable cross domain JSON
I'm using a generic XMLhttprequest builder:
var req; // Request object
function loadXMLDoc(url,params){
// branch for native XMLHttpRequest object
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = processReqChange;
req.open("GET", url, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.setRequestHeader("Content-length", params.length);
req.setRequestHeader("Connection", "close");
req.send(params);
// branch for IE/Windows ActiveX version
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = processReqChange;
req.open("GET", url, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.setRequestHeader("Content-length", params.length);
req.setRequestHeader("Connection", "close");
req.send(params);
}
}
}
I then have a handler :
function processReqChange(){
if (req.readyState == 4) {
if (req.status == 200) {
alert("Done");
} else {
//alert("There was a problem retrieving the data:\n" + req.statusText);
alert("Status Code = "+req.status);
alert("There was a problem retrieving the data:\n");
alert("Failed : object = "+req);
alert(req.responseXML);
alert("Failed : response = "+req.responseText);
alert("Failed : status = "+req.statusText);
}
}else{
}
}
But I keep getting a null response (statusText OK, status code 0). Any ideas?
Thanks in advance
You can't make a cross-domain ajax request. Look into whether or not they support JSONP, or use the FB.api method from their javascript SDK
http://developers.facebook.com/docs/reference/javascript/FB.api
EDIT: I didn't read your post very thoroughly when I replied.
I see that you're adding the callback name to your ajax request, which isn't going to do any good because you're still making an XHR request, so it will still fail cross-domain. You seem to be misunderstanding how JSONP works.
Normally I'd just suggest using a framework like jQuery to abstract out the work that you shouldn't have to reinvent. If you're absolutely dedicated to doing this without jQuery, start by reading the wikipedia article on how JSONP works:
http://en.wikipedia.org/wiki/JSON#JSONP
The basic idea is:
Create a script node where the src attribute looks just like the URL you're trying to request now.
The server will respond with something like : methodname({"foo": "bar"}); instead of just JSON. Since this is being requested via a script node, your browser will execute the "methodname" function and pass in the results.
implement methodname(response) function to handle the response (i.e. do the work you intended to do in processReqChange)
Remove this line and try again:
req.setRequestHeader("Connection", "close");
It sets up the connection to close automatically, often before the send is complete.

Categories

Resources