tags:

views:

544

answers:

3

Hello everyone,

I am using the following script to monitor whether I can connect to a web site in a regular interval (10 seconds in my sample code). I met with two issues, any ideas how to solve them?

  1. If a web site is very slow and no response within 10 seconds (making PingWebSite not return), I find 2 second call to PingWebSite will be executed because of 10 second interval arrives. My purpose is I want only one call to PingWebSite is under execution, and if 10 seconds interval arrives and previous PingWebSite is executing, I want to prevent current PingWebSite from execution. Any ideas how to solve this?

  2. I find a strange issue, when I connect to a very slow web site, and code path executes to "alert("connecting");", then I expect exception to be thrown for timeout, but in my debug, no exception is thrown. Any ideas how to catch timeout exception?

Here is my code,

var index = 0;

function setup() {
    window.setInterval(PingWebSite, (10 * 1000));
}

function PingWebSite() {

    var http_request = new XMLHttpRequest();
    try {
        http_request.open("GET", "http://www.google.com", true);
        http_request.onreadystatechange = function() {
            if (http_request.readyState == 4) {
                if (http_request.status == 200) {
                    MonitorInformation.innerText = "http://www.google.com" + " Connection ok";
                    alert("ok");
                }
                else {
                    alert("fail");
                }
                http_request = null;
            } // if if (http_request.readyState == 4)
            else {
                // if execute here, no exception will be thrown
                alert("connecting");
            }
        }  // end of function
        http_request.send(null);
    } // try
    catch (e) {
        alert("service is not available");
    }
}

EDIT 1: I have followed advice here to modify my code. Here is the below version. The new issue is index value (e.g. 0) will be prompted in alert message box before ok/fail alert message box. I think index value (e.g. 0) should be prompted in alert message box after ok/fail alert message box. Any ideas why?

var index = 0;
var http_request;
var xhrTimeout;
var chkConn;

function setup() {
    chkConn = window.setInterval(PingWebSite, (10 * 1000));
}

function WebMonitorTimeout() {
    http_request.abort();
    alert("timeout");
    index = index + 1;
}

function PingWebSite() {

    http_request = new XMLHttpRequest();
    http_request.open("GET", "http://www.google.com", true);

    http_request.onreadystatechange = function()
    {
        if (http_request.readyState == 4) {
            if (chkConn) { clearInterval(chkConn); }
            if (http_request.status == 200) {
                alert("ok");
                index = index + 1;
                if (xhrTimeout) { clearTimeout(xhrTimeout); }
            }
            else {
                alert("fail");
                index = index + 1;
                if (xhrTimeout) { clearTimeout(xhrTimeout); }
                }

                http_request = null;
            } //if (http_request.readyState == 4)

    }    // end of event function
    http_request.send(null);
    xhrTimeout = setTimeout("WebMonitorTimeout();", 30000);
    alert(index);
    chkConn = window.setInterval(PingWebSite, (30 * 1000));
}

thanks in advance, George

+1  A: 
Blixt
Thanks Blixt, 1. but if I do not call setInterval, how to make sure I ping web site in a regular interval? I need to ping web site in a regular interval, not just once. 2. When onreadystatechange will be called? Only when we call send?
George2
1) The `setTimeout` will make sure that the `PingWebSite` function is called regularly. It won't be called exactly every 10 seconds because that will cause the problems you had. Instead it will be called 10 seconds after the completion of a previous request. So if all requests take 1 second to finish on average, `PingWebSite` will be called every 11th second on average. This is so that even if a request takes 20 seconds to finish, it will still wait 10 seconds before doing the next request, instead of starting two new requests while the first request hasn't even finished.
Blixt
2) `onreadystatechange` will be called most of the time, although in the case of a timeout or other network problems it might not reach state 4. To solve this, many frameworks wait a certain amount of seconds before calling `http_request.abort()` and triggering a "timeout" error. See the jQuery source, or Ramiz Uddin's example.
Blixt
Thanks Blixt, I have followed your advice and implemented my new version of code. Please refer to EDIT 1 section of my original post. The new issue is -- I think index value (e.g. 0) should be prompted in alert message box after ok/fail alert message box, but actually index message box prompted before. Any ideas why?
George2
I am wondering whether setTimeout will (1) return immediately and call WebMonitorTimeout in 30 seconds if timeout is not cleared, or (2) will block the current execution for 30 seconds, then call WebMonitorTimeout?
George2
`setTimeout` and `setInterval` are non-blocking functions. The following code will continue to be executed directly after they have been called. `index` will not have had time to update before the first `alert` call.
Blixt
+2  A: 

Duplicate of http://stackoverflow.com/questions/1184638/javascript-connect-to-web-site-code-not-working/1184650#1184650

You can't do Cross Site XHR requests because of browser security

AutomatedTester
The readyState won't fire because the line above will stop because of security. Same Origin Policy will stop the script from running
AutomatedTester
@David I don't believe he is running on the google domain so this won't work.
AutomatedTester
It could work with google.com without any issues. Why do you think my question is because of cross-site security? :-)
George2
JavaScript has a same domain policy so you can not read other domains [example.com can not read stackoverflow.com], if you can do this, it means your browser settings are really low and would mean you are a hacker's dream.
epascarello
@George2 The reason why its not firing properly is because of the line above breaking the Same Origin Policy in JavaScript. The browser will normally ignore the rest of the script. You *may* get around it you use IEHTA or Firefox chrome to run the script
AutomatedTester
Thanks, I know why my code works. I tested locally -- write javascript code locally and save it as a .js file, then open a browser with an html file and embed the javascript in the html file. In this case, I should be able to call external web site like google, correct?
George2
@epascarello and @AutomatedTester, I have met a new issue (please refer to EDIT 1 sectio of my original code for my update version of code) -- the new issue is -- I think index value (e.g. 0) should be prompted in alert message box after ok/fail alert message box, but actually index message box prompted before. Any ideas why?
George2
I am wondering whether setTimeout will (1) return immediately and call WebMonitorTimeout in 30 seconds if timeout is not cleared, or (2) will block the current execution for 30 seconds, then call WebMonitorTimeout?
George2
I have a related question, could you help here please? http://stackoverflow.com/questions/1192716/javascript-same-origin-security-issue
George2
+1  A: 
<SCRIPT language=javascript>
// Needed for IE6 and older to replicate the standard XMLHttpRequest object
if (window.ActiveXObject && !window.XMLHttpRequest){window.XMLHttpRequest =
 function(){progIds=new Array("Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0",
 "Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP",
 "Microsoft.XMLHTTP");for(i in progIds){try{return new
 ActiveXObject(progIds[i]);}catch(ex){alert(progIds[i]);}}return null;};}

// Standard asynchonous AJAX code
var xhr = new XMLHttpRequest();
// You would normally trade out the location.href with an actual .ashx
// page.  It's like this here only for testing, thereby requesting this
// same page back from the server.
xhr.open("POST",location.href,true);

// The function that will be called asynchronously when the server sends
// back its response
xhr.onreadystatechange=function(){
   // If you're using the file system instead of a web server then xhr.status
   // will come back as 0, not 200.  And of course if the page isn't found
   // then a web server will send back a status of 404.  xhr.readyState is 4
   // when the page is done.
   if (xhr.readyState == 4 && xhr.status == 200) {
      clearTimeout(xhrTimeout);   // Looks like we didn't time out!
      // Use xhr.responseText to parse the server's response
      alert(xhr.responseText);
   }
}

// Now that we're ready to handle the response, we can make the request
xhr.send("My excellent post info");
// Timeout to abort in 5 seconds
var xhrTimeout=setTimeout("ajaxTimeout();",5000);
function ajaxTimeout(){
   xhr.abort();
   alert("Well dang, the AJAX request timed out.  Did you lose network "+
         "connectivity for some reason?");
   // Note that at this point you could try to send a notification to the
   // server that things failed, using the same xhr object.
}
</SCRIPT>
Ramiz Uddin
You have an `alert` on line 7 in the catch, that can get very annoying. I guess, that is left from debugging.
Boldewyn
Thanks Ramiz, excellent sample! 2 quesitons. :-)1. I noticed in your code you do not call setInterval, I need to ping web site in a regular interval, not just once, I am confused how you implement this in your code? 2. when the function assigned to onreadystatechange will be called? When we call send on xhr or when any response from server is received? Will the function be called when there is timeout?
George2
Another question is if the return code from web site is not 200, how does your code handles this issue?
George2