Hello. I've been using a very helpful AJAX-based script called AJAXTwits to load multiple Twitter timelines for a sports team into a div. The nice thing about the script is that it (1) combines multiple timelines into one chronological timeline and (2) caches the xml for faster loading. Every so often, though, Twitter's feeds go down, meaning that (i) the caching fails, (ii) the content won't load (I get stuck with the loading message), and (iii) if the problem is big enough, the whole page (not just div) breaks and throws a 404 error.

So, I'd like to add error-handling -- specifically, a pre-written message/div-content that will replace the loading message if the content doesn't load within a set amount of time. I've found some nice examples on this forum on how to handle timeouts. But those deal with a much simpler function/script syntax that does not call out to other js/php files. Being a cut/paste/emulate programmer, I'm having trouble adapting that.

The main html looks like this:

<ul id='AjaxTwits'>
    <li id='AjaxTwitsLoader'>
        <em>Loading tweets</em>
    </li>
</ul>

<script type="text/javascript">
    getAjaxTwits("AjaxTwits/AjaxTwitsRequest.php", 6);
</script>

Without digging into the script and php files, is there any kind of error/timeout handling that can be placed into this html? Any help appreciated!

You can try something like this inside the callBack function (or requestHandler).

var timer = 0;
var requestHandler = function() {
   start = setTimeout( this, 1000 );
   var div = document.getElementById("someDivId");
   if ( timer === 10 && xmlHttp.readyState !== 4 ) { // If the countdown timer reaches its time limit, you can abort the current AJAX request. 
   xmlHttp.abort();
   div.innerHTML = "Request failed!";
   return false;
   } if ( xmlHttp.readyState === 4 ) { // else If the timer < 10sec. and completed the final state, you can then continue to process the whole request.

   clearTimeout( start );
   delete start;
   div.innerHTML = xmlHttp.responseText;
   } ++timer;
};

You can try something like this inside the callBack function (or requestHandler).

Thank you for the quick response! I'm not sure I understand where to insert the code, though. I've pasted below the js file. If you could point me in the right direction, I'd appreciate it!

function sendAjaxRequest(url, eventhandler) {
	if (window.ActiveXObject) {
		var xhr = new ActiveXObject("Microsoft.XMLHTTP");
	} else if (window.XMLHttpRequest) {
		var xhr = new XMLHttpRequest();
	}

	xhr.onreadystatechange = function() {
	if(xhr.readyState == 4)
		if(xhr.status == 200) {
			eventhandler(xhr);
		} else {
			document.body.innerHTML = xhr.responseText;
		}
	}

	xhr.open("POST", url, true );
	xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	xhr.send("");
}

function getAjaxTwits(url, itemCount) {
	var twitter = document.getElementById('AjaxTwits');
	var twitterload = document.getElementById('AjaxTwitsLoader');
	
	sendAjaxRequest(url, function(ajaxRequest) {
		if (ajaxRequest.responseText) {
					
			var ans = eval('(' + ajaxRequest.responseText + ')');

			if (ans.item) {
				twitter.removeChild(twitterload);
				
				for (var i = 0; i < itemCount; i++) {
					var li = document.createElement("LI");
					li.className = "twitter-item";				
									
					var message = hyperlinks(ans.item[i].description);
					message = twitter_users(message);
					
					li.innerHTML += "<font color='#D36727'><u>" + ans.item[i].feedname + "</u>:</font> ";
					li.innerHTML += message + " [";
									
		var a = document.createElement("A");
					//	a.href = ans.item[i].url;
					
						a.href = "http://www.twitter.com/" + ans.item[i].user;
											
						a.className = "twitter-link";
					//	a.innerHTML = "posted " + ans.item[i].date;
					
					a.innerHTML = "<span style='white-space:nowrap;'>" + ans.item[i].date + "</span>";
					
					a.target = "_blank";
											
					li.appendChild(a);
					
					li.innerHTML += "]";
					
					twitter.appendChild(li);
				}
			}
		}
	});	
}

function hyperlinks(text) {
	text = text.replace(/\s(http:\/\/[a-z][a-zA-Z0-9\/\*\-\?\.\&\%\$]*)/ig," <a href=\"$1\" class=\"twitter-link\" \"target\">$1</a>");
	text = text.replace(/\s([a-zA-Z]+:\/\/[a-z][a-z0-9\_\.\-]*[a-z]{2,6}[a-zA-Z0-9\/\*\-\?\&\%]*)([\s|\.|\,])/ig," <a href=\"$1\" class=\"twitter-link\" \"target\">$1</a>$2");
	// match www.something.domain/path/file.extension?some=variable&another=asf%
	text = text.replace(/\s(www\.[a-z][a-z0-9\_\.\-]*[a-z]{2,6}[a-zA-Z0-9\/\*\-\?\&\%]*)([\s|\.|\,])/ig," <a href=\"http://$1\" class=\"twitter-link\" \"target\">$1</a>$2");      
    
	return text;
}

function twitter_users(text) {
    text = text.replace(/([\.|\,|\:|\¡|\¿|\>|\{|\(]?)@{1}(\w*)([\.|\,|\:|\!|\?|\>|\}|\)]?)\s/ig, "$1<a href=\"http://twitter.com/$2\" class=\"twitter-user\" \"target\">@$2</a>$3 ");
    return text;
}

You must declare this timer variable oustide of your sendAjaxRequest( arguments... ) function. var timer = 0; // Declared as global variable. The rest of the editing procedure will take part on this portion of the script:

xhr.onreadystatechange = function() {
   start = setTimeout( this, 1000 );
   if ( timer === 10 && xhr.readyState !== 4 ) { // Specify the number of timer limit, it is currently set to 10sec delay.

/* Add the things that you need to process if the requested content failed to load with the given time limit. */

   clearTimeout( start );
   xhr.abort();
   document.body.innerHTML = "Loading failed!"; 
   return false;
   }
 if ( xhr.readyState === 4 && xhr.status === 200 ) { //The request completed the execution over its timer limit.
   clearTimeout( start );
   delete start;
   document.body.innerHTML = xhr.responseText;
   } ++timer;
}; // Callback reference ENDED.

hope it goes wel with your AJAX handler...

essential

Thank you for your quick response again. I apologize that I'm still not getting it. I'm really sorry. No doubt I'm in over my head at this point, but I'd like to get it figured out and to learn from it.

Based on what you suggested, I did two things (I'm sure neither of which was correct). First, I added the global timer variable into the php file (insertion in bold):

<?php

[B]  var timer = 0; // Declared as global variable.[/B]

	//include AjaxTwits and create an object
	include('AjaxTwits.php');
	$ajaxTwits = new AjaxTwits;
	
	//set the cache to a writable folder, to save xml files
	$ajaxTwits->cachefolder = "ajaxtwits/cache";
	//the amount of minutes the feed is cached
	$ajaxTwits->cacheTime = 2;
	
	//the amount of items you'll show
	$ajaxTwits->itemCount = 15;
	
	//add your twitter account feeds
	$ajaxTwits->addTimeline("xxxx", "xxxx");
	$ajaxTwits->addTimeline("yyyy", "yyyy");
		
	
	//disable human time and output just Y/m/d date format
	$ajaxTwits->humanTime = true;
	
	//this will output the information, JSON is for the Javascript application
	$ajaxTwits->outputFeed("json");
?>

Second, I added the script you suggested into my preexisting js as shown below (insertion in bold):

function sendAjaxRequest(url, eventhandler) {
	if (window.ActiveXObject) {
		var xhr = new ActiveXObject("Microsoft.XMLHTTP");
	} else if (window.XMLHttpRequest) {
		var xhr = new XMLHttpRequest();
	}

[b]	xhr.onreadystatechange = function() {
   start = setTimeout( this, 1000 );
   if ( timer === 5 && xhr.readyState !== 4 ) { // Specify the number of timer limit, it is currently set to 10sec delay.

/* Add the things that you need to process if the requested content failed to load with the given time limit. */[/B]

  
	
	
	xhr.onreadystatechange = function() {
	if(xhr.readyState == 4)
		if(xhr.status == 200) {
			eventhandler(xhr);
		} else {
			document.body.innerHTML = xhr.responseText;
		}
	}

	xhr.open("POST", url, true );
	xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	xhr.send("");
}


function getAjaxTwits(url, itemCount) {
	var twitter = document.getElementById('AjaxTwits');
	var twitterload = document.getElementById('AjaxTwitsLoader');
	
	sendAjaxRequest(url, function(ajaxRequest) {
		if (ajaxRequest.responseText) {
					
			var ans = eval('(' + ajaxRequest.responseText + ')');

			if (ans.item) {
				twitter.removeChild(twitterload);
				
				for (var i = 0; i < itemCount; i++) {
					var li = document.createElement("LI");
					li.className = "twitter-item";				
									
					var message = hyperlinks(ans.item[i].description);
					message = twitter_users(message);
					
					li.innerHTML += "<font color='#D36727'><u>" + ans.item[i].feedname + "</u>:</font> ";
					li.innerHTML += message + " [";
									
		var a = document.createElement("A");
					//	a.href = ans.item[i].url;
					
						a.href = "http://www.twitter.com/" + ans.item[i].user;
											
						a.className = "twitter-link";
					//	a.innerHTML = "posted " + ans.item[i].date;
					
					a.innerHTML = "<span style='white-space:nowrap;'>" + ans.item[i].date + "</span>";
					
					a.target = "_blank";
											
					li.appendChild(a);
					
					li.innerHTML += "]";
					
					twitter.appendChild(li);
				}
			}
		}
	});	


function hyperlinks(text) {
	text = text.replace(/\s(http:\/\/[a-z][a-zA-Z0-9\/\*\-\?\.\&\%\$]*)/ig," <a href=\"$1\" class=\"twitter-link\" \"target\">$1</a>");
	text = text.replace(/\s([a-zA-Z]+:\/\/[a-z][a-z0-9\_\.\-]*[a-z]{2,6}[a-zA-Z0-9\/\*\-\?\&\%]*)([\s|\.|\,])/ig," <a href=\"$1\" class=\"twitter-link\" \"target\">$1</a>$2");
	// match www.something.domain/path/file.extension?some=variable&another=asf%
	text = text.replace(/\s(www\.[a-z][a-z0-9\_\.\-]*[a-z]{2,6}[a-zA-Z0-9\/\*\-\?\&\%]*)([\s|\.|\,])/ig," <a href=\"http://$1\" class=\"twitter-link\" \"target\">$1</a>$2");      
    
	return text;
}

function twitter_users(text) {
    text = text.replace(/([\.|\,|\:|\¡|\¿|\>|\{|\(]?)@{1}(\w*)([\.|\,|\:|\!|\?|\>|\}|\)]?)\s/ig, "$1<a href=\"http://twitter.com/$2\" class=\"twitter-user\" \"target\">@$2</a>$3 ");
    return text;
}

[B] clearTimeout( start );
   xhr.abort();
   document.body.innerHTML = "Loading failed!"; 
   return false;
   }
 if ( xhr.readyState === 4 && xhr.status === 200 ) { //The request completed the execution over its timer limit.
   clearTimeout( start );
   delete start;
   document.body.innerHTML = xhr.responseText;
   } ++timer;
}; // Callback reference ENDED.[/B]

}

If you point out where I'm erring, I would really appreciate it! Thanks again!

I just figured out that I completely misunderstood the direction that Essential so generously gave. I'm having trouble editing my response above, though, so I'm just replying.

I'm still not sure I added the global timer variable properly. But I think this is what you had in mind for the insertion (the bolded part replacing the old hxr.onreadystatechange handling:

function sendAjaxRequest(url, eventhandler) {

	if (window.ActiveXObject) {
		var xhr = new ActiveXObject("Microsoft.XMLHTTP");
	} else if (window.XMLHttpRequest) {
		var xhr = new XMLHttpRequest();
	}

[B]xhr.onreadystatechange = function() {
   start = setTimeout( this, 1000 );
   if ( timer === 5 && xhr.readyState !== 4 ) { // Specify the number of timer limit, it is currently set to 10sec delay.

/* Add the things that you need to process if the requested content failed to load with the given time limit. */

   clearTimeout( start );
   xhr.abort();
   document.body.innerHTML = "Loading failed!"; 
   return false;
   }
 if ( xhr.readyState === 4 && xhr.status === 200 ) { //The request completed the execution over its timer limit.
   clearTimeout( start );
   delete start;
   document.body.innerHTML = xhr.responseText;
   } ++timer;
}; // Callback reference ENDED.[/B]

	xhr.open("POST", url, true );
	xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	xhr.send("");
}

function getAjaxTwits(url, itemCount) {
	var twitter = document.getElementById('AjaxTwits');
	var twitterload = document.getElementById('AjaxTwitsLoader');
	
	.....

Unfortunately, it's still not working....

Here's a complete document sample that you can run offline with your browser. Just be sure that you'll provide valid test file on its sendAjaxRequest(someValidFile.txt) url parameter.

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html id="xhtml10S" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://www.w3.org/2005/10/profile">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta http-equiv="Window-Target" content="_top" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>Free Live Help!</title>
<script type="text/javascript">
// <![CDATA[
var timer = 0;
var xhr;
var method = "POST";

var clock = function() {
countdown = setTimeout( "clock()", 1000 ); ++timer;
   return timer;
};

var sendAjaxRequest = function( url, eventhandler ) {
var div = (( "getElementById" in document ) ? document.getElementById("testdiv") : document.all.testdiv );

   try {
      if ( "XMLHttpRequest" in window ) {
      xhr = new XMLHttpRequest(); 
      } else if ( "ActiveXObject" in window ) {
      var client = [ "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" ];
         try {
            for ( var i = 0; i < client.length; i++ ) {
            xhr = new ActiveXObject( client[ i ] ); 
            }
         } catch( er ) { }
      }  
   } catch( e ) {
      if ( "createRequest" in window ) {
      xhr = window.createRequest();
      } xhr = null;
   } if ( xhr !== null ) {
   (( "overrideMimeType" in xhr ) ? xhr.overrideMimeType("text/xml") : xhr );
   xhr.onreadystatechange = function() {
   clock(); // Activate the timer
   timer = (( timer < 10 ) ? "0" : "" ) + timer;
      if ( timer < 5 && xhr.readyState === 4 ) { 
      clearTimeout( countdown );
      delete countdown;
      div.innerHTML = "<p style=\"color : purple;\">Request completed in <span style=\"color : red;\">" + timer + "</span> seconds!</p>\n";
      div.innerHTML += "<hr />\n";
      div.innerHTML += "<span style=\"letter-spacing : 4px; color : green;\">" + xhr.responseText + " —</span>";
      return true;
      } xhr.abort();
        clearTimeout( countdown );
      delete countdown;
div.innerHTML = "<span style=\"letter-spacing : 4px; color : purple;\">Request failed —</span>";  
   };
   xhr.open( method, encodeURIComponent( url ), true );
   (( method === "POST" && "setRequestHeader" in xhr ) ? xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") : xhr );
   xhr.send( "" );
   return true;
   } alert( "Your browser does not handle AJAX Request!" );
};
window.onload = function() {
sendAjaxRequest("test.txt");
};
// ]]>
</script>
</head>
<body>
<div id="testdiv"></div>
</body>
</html>

Well, with BIG BIG thanks to 'essential' for his support, I can finally mark this solved. Here is the key part of the timeout handling excerpt:

var timer = 0;
var xhr;
var method = "POST";
var clock = function() {
countdown = setTimeout( "clock()", 1000 ); ++timer;
   return timer;
}

var sendAjaxRequest = function( url, eventhandler ) {
var div = (( "getElementById" in document ) ? document.getElementById("AjaxTwitsLoader") : document.all.AjaxTwitsLoader );
   try {
      if ( "XMLHttpRequest" in window ) {
      xhr = new XMLHttpRequest(); 
      } else if ( "ActiveXObject" in window ) {
      var client = [ "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" ];
         try {
            for ( var i = 0; i < client.length; i++ ) {
            xhr = new ActiveXObject( client[ i ] ); 
            }
         } catch( er ) { }
      }  
   } catch( e ) {
      if ( "createRequest" in window ) {
      xhr = window.createRequest();
      } xhr = null;
   } if ( xhr !== null ) {
   (( "overrideMimeType" in xhr ) ? xhr.overrideMimeType("text/xml") : xhr );
   xhr.onreadystatechange = function() {
   clock(); // Activate the timer
      if ( timer < 10 ) {
         if ( xhr.readyState === 4 ) {
          // if ( xhr.status === 200 ) { 
         clearTimeout( countdown );
         delete countdown;
         eventhandler( xhr );
         // }
         } return true;
      } else {
      div.innerHTML = "<img src='/images/twitter-bird-error2.gif' align='left' style='margin-left:-10px;'><br><center><i>temporarily unable to connect to Twitter....</i>";
      }  
   }; xhr.open( "POST", url, true );
   //(( method === "POST" && "setRequestHeader" in xhr ) ? xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") : xhr );
   xhr.send( "" );
   return false;
   } //alert( "Your browser does not handle AJAX Request!" );
   
   
}

function getAjaxTwits(url, itemCount) {

...
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.