Why do blank alert statements affect execution of other code? - javascript

I'm working on the front page of a website that will have a section that will show news articles. The articles will fade into the next one every 10 seconds. For some reason the code only executes correctly (keep in mind it's not entirely finished so there may be other errors) with the inclusion of a couple alert() statements. These were previously in there just for debugging, but currently, it seems as though they serve some functional purpose. Without them, the code will give different results if any at all.
I'm mainly a Java programmer, so there are probably some idiosyncrasies about JavaScript alert() statements that I'm not familiar with. The other odd thing that I noticed was that at times I would run the code multiple times with no changes and get different results. I used some of the alert() statements in the loadArticles() function to output the value of i and would occasionally get a different result without changing the code. The only idea I have so far is that my computer is taking time to run the statements that is allowing some other process to finish, but there shouldn't be any multi-threading involved.
The init() function is called in onload from the HTML and there's a div with id="news" somewhere in the center of the page.
On top of the main question, extra credit for anyone who could help out with why I'm sometimes not getting the articles to fade in and out. I'm pretty sure it has something to do with the article or container being null, but I haven't had time to get to that yet.
Here's the JavaScript:
var article_count = 0;
var count = 0;
function init() {
getArticleCount();
loadArticles();
changeSlide();
resize();
resize();
}
function getArticleCount() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
article_count = xmlhttp.responseText;
}
};
xmlhttp.open("GET", "getArticleCount.php", true);
xmlhttp.send();
}
function loadArticles() {
alert();
for(i = 1; i <= article_count; i++) {
alert();
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert();
var news = document.createElement("iframe");
news.className = "news";
news.src = "articles/" + xmlhttp.responseText;
news.style.zIndex = 0 - i;
var container = document.getElementById("news");
container.appendChild(news);
}
};
alert();
xmlhttp.open("GET", "getArticles.php?q=" + i, true);
xmlhttp.send();
alert();
}
}
function changeSlide() {
var article = document.getElementsByClassName("news")[count];
var interval = setTimeout(function() {
var fadeOut = article.fadeOut(1000, function() {
if(count < article_count) {
count++;
changeSlide();
} else {
count = 0;
resetSlides();
}
});
}, 10000);
}
function resetSlides() {
var articles = document.getElementsByClassName("news");
for(j = 0; j < article_count; j++) {
var fadeIn = articles[j].fadeIn(1000);
}
changeSlide();
}
function resize() {
var body = $(document.body);
var news = $("#news");
$("#menu_left").width((body.outerWidth() - news.outerWidth()) / 2 - 3);
$("#menu_right").width((body.outerWidth() - news.outerWidth()) / 2 - 3);
$("#menu_contact").width(body.outerWidth());
}

There are lots of mistakes in your code, mostly related to the asynchronous nature of Ajax calls. You will need to more about programming with asynchronous operations to write correctly functioning and reliable and consistent code.
alert() statement change the relative timing of asynchronous operations (such as Ajax calls vs. when your other code runs.
In general, stop using alert() statements at all as a debugging tool because it can influence the timing too much. Instead, use console.log() statements. Since console.log() just outputs to the console and does not block execution of the Javascript thread at all, it will not impact the timing of things nearly as much as an alert() statement.
Here's a trivial example to show you how an alert() can change the timing of things:
var img = new Image();
img.src = "http://somedomain.com/myimg.jpg";
alert("Press OK to continue");
if (img.complete) {
console.log("image is done loading");
} else {
console.log("image is not yet done loading");
}
With the alert statement, you will get image is done loading in the console. Without the alert, you will get image is not yet done loading. The alert has changed the flow of your code.
Another thing that can affect the timing of your code is whether resources are in the browser cache or must be loaded over the network. In nearly all cases, properly written code that only uses resources when it knows they have been loaded will continue to work in either case. But, in cases with poorly written code, you may see a different behavior the first time a page is loaded vs. subsequent times when some of the resources are now cached.
To fix your specific code, you need to program asynchronously. That means using completion handlers for asynchronous operations like Ajax calls and calling callbacks to notify other code when asynchronous operation are done.
For example, your getArticleCount() function is asynchronous. It will finish its Ajax operation some time AFTER the getArticleCount() has already returned. You can change it to accept a callback like this:
function getArticleCount(callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback(xmlhttp.responseText);
}
};
xmlhttp.open("GET", "getArticleCount.php", true);
xmlhttp.send();
}
And, then you use it like this:
getArticleCount(function(cnt) {
// in here you can use the article count
});
As for your .fadeOut() and .fadeIn() operations, those are not native DOM methods so you can't call them on DOM objects like you are trying to do. It appears that you are attempting to use the jQuery methods with this name. To do, you must load jQuery into your page and then you must create jQuery objects that contain the relevant DOM objects and call .fadeOut() and .fadeIn() on the jQuery objects, not on the DOM objects.
Your loadArticles() function can be fixed by putting the ajax calls inside an internal function inside the method. This will allow each ajax operation you are starting to have it's own separate variables rather than having all of them collide and try to use the same variables. You can do that by using an IIFE (Immediately Invoked Function Expression) inside your for loop like this:
function loadArticles() {
for (i = 1; i <= article_count; i++) {
(function() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var news = document.createElement("iframe");
news.className = "news";
news.src = "articles/" + xmlhttp.responseText;
news.style.zIndex = 0 - i;
var container = document.getElementById("news");
container.appendChild(news);
}
};
xmlhttp.open("GET", "getArticles.php?q=" + i, true);
xmlhttp.send();
})();
}
}
Note, because Ajax operations have an indeterminate timing, this code does not guarantee that the items you are adding to the page will be added in any particular order. They are more than likely to be added in the order of your for loop, but that is not guaranteed. If the serve happens to be quicker with one of the requests vs. another, it might finish first and get added to the page first, even though it was not the first one requested.
And, since your resize() function appears to use jQuery, you will find it a TON easier to use jQuery's ajax support rather than coding your own Ajax calls. Plus with jQuery Ajax, you can use the built-in promise interface to make your asynchronous programming and error handling substantially easier.

The reason removing the alert calls in your code made it not work anymore is because your functions getArticleCount(), loadArticles() are making asynchronous requests for data. Alert popups made the program halt, while the AJAX request was off retrieving data and it had returned the result by the time you closed the alert popup.
You can change those 2 functions to execute a callback function as a way to let other functions know that it's finished:
function init() {
getArticleCount(function() {
// finished getting article count
loadArticles(function() {
// finished loading articles
changeSlide();
resize();
resize();
});
});
}
function getArticleCount(callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
article_count = xmlhttp.responseText;
callback(); // done
}
};
xmlhttp.open("GET", "getArticleCount.php", true);
xmlhttp.send();
}
function loadArticles(callback) {
for(i = 1; i <= article_count; i++) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var news = document.createElement("iframe");
news.className = "news";
news.src = "articles/" + xmlhttp.responseText;
news.style.zIndex = 0 - i;
var container = document.getElementById("news");
container.appendChild(news);
callback(); // done
}
};
xmlhttp.open("GET", "getArticles.php?q=" + i, true);
xmlhttp.send();
}
}
As a side note, you can debug using the browser Developer Tools, and use console.log() and debugger;

XMLHttpRequest is an asynchronous call.
You make a getArticleCount request in order to get a count of articles.
Then, you have a loop:
for (i = 1; i <= article_count; i++) {
getArticleCount request didn't complete by the time of this loop, and article_count is still equal to zero. You need to use onreadystatechange and move your consequent dependent calls into callbacks:
function init() {
getArticleCount();
}
function getArticleCount() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
article_count = xmlhttp.responseText;
loadArticles();
}
};
xmlhttp.open("GET", "getArticleCount.php", true);
xmlhttp.send();
}
function loadArticles() {
var container = document.getElementById("news");
for(i = 1; i <= article_count; i++) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var news = document.createElement("iframe");
news.className = "news";
news.src = "articles/" + xmlhttp.responseText;
news.style.zIndex = 0 - i;
container.appendChild(news);
}
};
xmlhttp.open("GET", "getArticles.php?q=" + i, true);
xmlhttp.send();
}
}
Anyway, you have some architectural problems:
Making count request apart from data requests is redundant. Moreover, the value could change while you execute your articles.
Making many HTTP requests will cause a huge performance drop.
You need to make a single PHP-file, which will return a JSON array with all articles. Then, you will able to work with its length and every item, and it will work much faster while not causing any synchronization problems.

The alerts are (somewhat) syncronizing your ajax calls. You have dependencies between getArticleCount and loadArticles. The alert() at the top of loadArticles is causing execution to pause until you cancel the alert. In that time the AJAX request to "getArticleCount.php" has completed and assigned a value to article_count.
Without the alerts pausing execution, your code is non-deterministic b/c AJAX calls can not be strung together in a procedural fashion and behave synchronously. You will need to use a functional programming style to get AJAX calls to behave synchronously.
For example you could make write it like this
function init() {
getArticleCount(loadArticles);
resize();
resize();
}
function getArticleCount(callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//callback will be loadArticles()
callback.call(null, xmlhttp.responseText);
}
xmlhttp.open("GET", "getArticleCount.php", true);
xmlhttp.send();
}
function loadArticles(articleCnt) {
for(i = 1; i <= articleCnt; i++) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var news = document.createElement("iframe");
news.className = "news";
news.src = "articles/" + xmlhttp.responseText;
news.style.zIndex = 0 - i;
var container = document.getElementById("news");
container.appendChild(news);
if(i == i){
//modify function to use passed in count instead of global
changeSlides(articleCnt);
}
}
};
xmlhttp.open("GET", "getArticles.php?q=" + i, true);
xmlhttp.send();
}
}
When calling getArticleCount the callback parameter would be loadArticles which has been modified to accept the article_count as a parameter instead of using the global. The above code will fix your issue. You should modify other functions to take a local article count and stop relying on the global.

Related

Loading images as base64 calls from Javascript

I am trying to implement a small photo show via a django webserver. Below you can find the javascript code that loads the pictures into the images array and changes the images every x miliseconds. It works if I only load one picture (without the loop) from my django server but it stops working with any kind of loop.
I would love to know why it does not work this way and would be more than happy to receive some other feedback about code improvements. I am not very familiar with ajax calls yet.
Moreover: Django Templates Engine provides a easy way to simplify urls used in the templates. Is there a way to use the {{% url %}} tag inside a .js File as well?
window.images = [];
window.current = 0;
window.imageCount = 2;
function loadImages(){
for(var i = 0; i < window.imageCount; i++){
loadNextImage(i);
}
showImage();
}
function loadNextImage(i) {
// https://wiki.selfhtml.org/wiki/JavaScript/XMLHttpRequest/
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
window.images.push("data:image/jpeg;base64," + xmlhttp.responseText);
}
};
xmlhttp.open('GET', "http://127.0.0.1:8000/mirror/"+i);
xmlhttp.send(null);
}
function showImage() {
if(window.current >= window.imageCount){
window.current = 0;
}
alert("current window count = "+ window.current);
document.getElementById('imgshow').src = window.images[window.current];
window.current = window.current + 1;
setTimeout(showImage, 50000);
}
The direct problem you are encountering is because XMLHttpRequest is Asynchronous and you are dealing with a race condition. Here is what your code now is doing:
Start a loop and tell the browser to que 2 XMLHttpRequests.
Perform the showImage method (even though we have no idea if those 2 AJAX Requests above have returned yet.)
An exception is thrown at this line: document.getElementById('imgshow').src = window.images[window.current]; because window.images is empty.
setTimeout(showImage, 50000); is never executed because of the exception at step 3.
Moving the setTimeout above the document.getElementById('imgshow').src = window.images[window.current]; line might work. However, this is a bad idea.
One solution would be to remove the loop at all, and lazy load the images (only load them once they are needed) as seen below:
window.images = [];
window.current = 0;
window.imageCount = 2;
function loadNextImage(i, callback) {
// https://wiki.selfhtml.org/wiki/JavaScript/XMLHttpRequest/
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
window.images.push("data:image/jpeg;base64," + xmlhttp.responseText);
callback.call();
}
};
xmlhttp.open('GET', "http://127.0.0.1:8000/mirror/"+i);
xmlhttp.send(null);
}
// Increments the image counter and loads the image if needed.
function stepImage() {
// If we have reached the end of the images, restart.
if(window.current >= window.imageCount){
window.current = 0;
}
// Make sure that the image is loaded in the images array,
// if not, load the image, then show it.
if(window.images.length <= window.current) {
loadNextImage(window.current, showImage);
}
// If it's already loaded, just show it.
else showImage();
}
// Displays an image onto the page.
function showImage() {
document.getElementById('imgshow').src = window.images[window.current];
// The counter is not incremented until the image is shown!
window.current++;
}
// Set a timer to render future images.
setInterval(stepImage, 3000);
// Render the first image.
stepImage();
<img id="imgshow" />

Javascript - updating textarea freezes browser tab

I am updating text in text area with javascript every 2 seconds, however sometimes happen that entire page freezes and you have to close the tab (other tabs in browser are working normally, this happens to all people visiting the page).
This is how my code looks like:
function ajaxSyncRequest(reqURL) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", reqURL, false);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send('server=" + server + "');
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200){
document.getElementById(\"1\").innerHTML = xmlhttp.responseText;
if (document.getElementById('check').checked) { document.getElementById(\"1\").scrollTop = document.getElementById(\"1\").scrollHeight; }
} else {
document.getElementById(\"1\").innerHTML = "Could not connect to remote server!";\n
}
}
}
And this is the 2 seconds timer:
function timer() {
ajaxSyncRequest("ConsoleGenerator");
window.setTimeout("timer()", 2000);
}
I am getting the text with POST method to Java Servlet. It works sometimes for hours and then it freezes and browser says "Page is not reposnding..." or sometimes it works just a few minutes and then it freezes...
Can anybody help please ?
(Assuming we fix the basic syntax errors in the code.) You're happily firing off a subsequent requests without waiting for previous ones to complete. If the ajax call ever takes more than two seconds, you'll have overlapping calls. That isn't a problem in and of itself unless your backend is serializing calls or similar, but it does set up a chaotic situation.
You're also making synchronous requests by specifying false as the third argument to the POST call. There's no need to make the request synchronous, and doing so (particularly every two seconds?!) will indeed tend to lock up the UI of the browser.
I would recommend waiting for the previous request to complete before scheduling the next one, and making the requests asynchronous so the browser UI isn't locked:
// Accept callback --------------v
function ajaxSyncRequest(reqURL, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", reqURL, true);
// async, not sync ----------^
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send('server=" + server + "');
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
document.getElementById("1").innerHTML = xmlhttp.responseText;
if (document.getElementById('check').checked) {
document.getElementById("1").scrollTop = document.getElementById("1").scrollHeight;
}
} else {
document.getElementById("1").innerHTML = "Could not connect to remote server!\n";
}
callback(); // <== Call it
}
}
function timer() {
ajaxSyncRequest("ConsoleGenerator", function() { // Pass in a callback
setTimeout(timer, 2000);
});
}
That will wait for the ajax to complete and then schedule another update two seconds later. If you want to include the time the ajax call took in the two seconds instead, we can do some basic math:
function timer() {
var started = Date.now();
ajaxSyncRequest("ConsoleGenerator", function() { // Pass in a callback
setTimeout(timer, Max.max(0, 2000 - (Date.now() - started));
});
}
Side note: No need for the window. prefix on setTimeout (though it's harmless provided nothing's shadowed the global window), and rather than passing a string to it, just pass a function reference.

Issue with for-loop and standard Javascript AJAX

I have some issues with a for-loop and AJAX. I need to fetch some information from a database, so I pass the incrementing variable to PHP to grab the information and then send it back. The trouble is that it skips immediately to the maximum value, making it impossible to store any of the information.
I would prefer not to use jQuery. It may be more powerful, but I find Javascript easier to understand.
Here is the JS code:
for (var i = 0; i <= 3; i++) {
var js_var = i;
document.getElementById("link").onclick = function () {
// ajax start
var xhr;
if (window.XMLHttpRequest) xhr = new XMLHttpRequest(); // all browsers
else xhr = new ActiveXObject("Microsoft.XMLHTTP"); // for IE
var url = 'process.php?js_var=' + js_var;
xhr.open('GET', url, false);
xhr.onreadystatechange = function () {
if (xhr.readyState===4 && xhr.status===200) {
var div = document.getElementById('test1');
div.innerHTML = xhr.responseText;
if (js_var == 2) {
var rawr = document.getElementById('test2');
rawr.innerHTML = xhr.responseText;
}
}
}
xhr.send();
// ajax stop
return false;
}
};
Here is the PHP code:
<?php
if (isset($_GET['js_var'])) $count = $_GET['js_var'];
else $count = "<br />js_var is not set!";
$con = mysql_connect("xxx","xxxxx","xxxx");
mysql_select_db('computerparty_d', $con);
$get_hs = mysql_query("SELECT * FROM hearthstone");
$spiller_navn = utf8_encode(mysql_result($get_hs,$count,1));
echo "$spiller_navn";
?>
what you actually are doing is binding an onclick event in your for-loop not sending ajax request, and the other point is, it immediately overrides the previous onclick handler which you have created in the previous iteration.
So if you want to add multiple listeners you should first consider using nested functions and closures to keep the i variable safe for each listener, and then use addEventListener instead of setting the onclick function. Considering these points you can do this instead:
for (var i = 0; i <= 3; i++) {
var clickFunc = (function (js_var) {
return function () {
// ajax start
var xhr;
if (window.XMLHttpRequest) xhr = new XMLHttpRequest(); // all browsers
else xhr = new ActiveXObject("Microsoft.XMLHTTP"); // for IE
var url = 'process.php?js_var=' + js_var;
xhr.open('GET', url, false);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var div = document.getElementById('test1');
div.innerHTML = xhr.responseText;
if (js_var == 2) {
var rawr = document.getElementById('test2');
rawr.innerHTML = xhr.responseText;
}
}
}
xhr.send();
// ajax stop
return false;
};
})(i);
document.getElementById("link").addEventListener("click", clickFunc);
}
Be aware that you're making an synchronous AJAX call, which is undesirable (it hangs the browser during the request, which might not end). You may have problems in some browsers with this because you're calling onreadystatechange, that shouldn't be used with synchronous requests.
It looks like you are making the AJAX request with a user click.
for (var i = 0; i <= 3; i++) {
var js_var = i;
document.getElementById("link").onclick
When this JS is executed it will override the "onclick" listener of "link" twice. First time it is assigned for the first time, second time it is overwritten, and the third time it is overwritten again. The result is that when the "link" element is clicked only the last listener exists, resulting in making a single AJAX request for the last configuration.
HTTP request are expensive(time), it might be worth to get all of the data in one request and then use client-side JS to sift through that data accordingly.
jQuery is not more powerful than JS, it is JS with a bunch of wrapper functions. My personal opinion is that once IE9 is no longer relevant, jQuery will be only used by people who know jQuery and not JS.

Maximum call stack size exceeded error when using ajax multiple times

I am writing a piece of code that should catch all ajax responses on a page. I managed to do this by overriding XMLHttpRequest.onreadystatechange for javascript direct ajax or by using ajaxComplete() for jQuery ajax.
My problem happens when I try to use ajax multiple times without creating a new XMLHttpObject, for example:
var xhr = new XMLHttpRequest();
xhr.open("GET", '/echo/json/', true);
xhr.send();
xhr.open("GET", '/echo/json/', true);
xhr.send()
This makes my code go haywire and I get the maximum stack error.
Here is my testing code on JSFiddle: http://jsfiddle.net/zxCfW/
var s_ajaxListener = {};
s_ajaxListener.tmpSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
console.log('additional state change');
};
XMLHttpRequest.prototype.send = function() {
s_ajaxListener.tmpOnReadyStateChange = this.onreadystatechange;
this.onreadystatechange = function() {
if (s_ajaxListener.tmpOnReadyStateChange){
s_ajaxListener.tmpOnReadyStateChange.apply(this, arguments);
}
if(this.readyState == 4 && this.status == 200) {
s_ajaxListener.callback();
this.onreadystatechange = s_ajaxListener.tmpOnReadyStateChange;
}
};
s_ajaxListener.tmpSend.apply(this, arguments);
};
$(document).ajaxComplete(s_ajaxListener.callback);
I believe this happens because the ajax calls are asynchronous so the original onreadystatechange doesn't reset to its default value, but I don't know how to solve this.

Javascript XMLHttpRequest issue

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?
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?
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
Duplicate of javascript connect to web site code not working
You can't do Cross Site XHR requests because of browser security
For your first problem, don't use setInterval – use setTimeout in the callback for your request:
http_request.onreadystatechange = function () {
if (http_request.readyState == 4) {
// ...
setTimeout(PingWebSite, 10000);
}
};
Don't forget to call your function once after it has been defined to start it off (after that setTimeout will be called every time after a request has finished.)
Note that in some cases you might not reach readyState 4. I haven't really looked into how other libraries handle those cases, but look at the source code of jQuery, for example, for inspiration.
<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>

Categories