Ajax chat basics

I’m currently working on my first ajax chat.
I built the basic view of the chat but i need some help understanding the best
way of retrieving new messages.

at first i tried checking for new messages each second to see if there are new messages from last second.
it worked fine but it did miss a few messages since it takes time to run the script therefore it’s not a perfect 1 second.

Then i tried storing the last message id in the cookies
so it was checking for messages with a higher id, and updating the cookie with that last message.
but this time it was duplicating many of the messages since the script runs again before the previous one is done (it’s alright with a high delay such as 1.5 seconds, but it’s a problem if people have slow connection)

So what’s the ideal way of checking for new messages?
Thank you.

One thing you could try is instead of setting an interval to check for new messages, you could set a timeout at the end of the function after you update your last message. That way you can’t call the function multiple times on the same id.

That’s what i am doing… sort of.
My code currently looks like this:


function get_messages(){ 
        
    var ajaxRequest;  // The variable that makes Ajax possible!
    try{
        // Opera 8.0+, Firefox, Safari
        ajaxRequest = new XMLHttpRequest();
    } catch (e){
        // Internet Explorer Browsers
        try{
            ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try{
                ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e){
                // Something went wrong
                die("Your browser broke!");
                return false;
            }
        }
    }   
    
    ajaxRequest.onreadystatechange = function(){
        if(ajaxRequest.readyState == 4){
            if(ajaxRequest.status == 200 || ajaxRequest.status == 304){
             ..... BUNCH OF CODE.....   
             }
    }    
    last_msg = document.getElementById("last_msg").innerHTML;                
    ajaxRequest.open("GET", "get_message.php?last_msg="+last_msg, true);
    ajaxRequest.send(null);
    start_timer();
}       

function start_timer() {
setTimeout ("get_messages()",1500);    
}         
   
   

The problem here is that i am running start_timer() again before i am getting the actual ajax response.
I tried putting start_timer() at the end of the ajax response but then it just won’t run, can’t figure out why.

Ah. I see the issue.
Ajax is Asynchronous, and your code is making the call then moving on before the new content is loaded. What you want to do is call start_timer() INSIDE the onreadystatechange callback, just after “… BUNCH OF CODE…” so it starts the next timer only after the fetched content is placed in and the last_msg is updated.

That’s what i’ve just explained :wink: when i did put the start_timer() at the end of the “bunch of code” inside onreadystatechange, it didn’t run it at all.

Oh, sorry about that. I have some code very much like this that I wrote when I was learning AJAX, let me dig that up…

By the way, it does work when i put it at the beginning of the “bunch of code”
and it looks fine, no double posts even with no delay at all, but i would
still like to know why it doesn’t work when i put it at the end :slight_smile:
maybe it has something to do with the code itself, so here’s the entire code:



function get_messages(){ 
        
    var ajaxRequest;  // The variable that makes Ajax possible!
    try{
        // Opera 8.0+, Firefox, Safari
        ajaxRequest = new XMLHttpRequest();
    } catch (e){
        // Internet Explorer Browsers
        try{
            ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try{
                ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e){
                // Something went wrong
                die("Your browser broke!");
                return false;
            }
        }
    }   
    
    ajaxRequest.onreadystatechange = function(){
        if(ajaxRequest.readyState == 4){
            if(ajaxRequest.status == 200 || ajaxRequest.status == 304){
                start_timer();
                var xml = ajaxRequest.responseXML;//!Important <-----------------
                var length = xml.getElementsByTagName("message").length; 
                    var last_msg = xml.getElementsByTagName("last_msg"); 
                for (i=0; i<length; i++)
                {   
                    var coolXML = xml.getElementsByTagName("message");
                    var name = coolXML[i].getElementsByTagName("content");
                    var id = coolXML[i].getElementsByTagName("user_id");
                    var msg_id = coolXML[i].getElementsByTagName("id")[0].firstChild.data;

                        var newmaindiv = document.createElement("div");
                            newmaindiv.id = msg_id; 
                            newmaindiv.style.cssText = "margin-top:5px;";
                        var newimage = document.createElement("img");
                            newimage.src = 'http://graph.facebook.com/'+id[0].firstChild.data+'/picture'; 
                        var newdiv = document.createElement("div");
                            newdiv.style.cssText = "display:inline;vertical-align:top;";
                            var newtxt = document.createTextNode(name[0].firstChild.data); 
                            newdiv.appendChild(newtxt);
                        document.getElementById("chatwindow").appendChild(newmaindiv);
                        document.getElementById(msg_id).appendChild(newimage); 
                        document.getElementById(msg_id).appendChild(newdiv); 
                   
                }       
                    
                    document.getElementById("chatwindow").scrollTop = document.getElementById("chatwindow").scrollHeight;
                    document.getElementById("last_msg").innerHTML = last_msg[0].firstChild.data;
                     

            } else {
            die("Something Broke!");
            }
          }
      
    }    
    last_msg = document.getElementById("last_msg").innerHTML;                
    ajaxRequest.open("GET", "get_message.php?last_msg="+last_msg, true);
    ajaxRequest.send(null);
}       

function start_timer() {
setTimeout ("get_messages()",500);    
}         
   
   


Okay, and you’ve tried this?


function get_messages(){ 
        
    var ajaxRequest;  // The variable that makes Ajax possible!
    try{
        // Opera 8.0+, Firefox, Safari
        ajaxRequest = new XMLHttpRequest();
    } catch (e){
        // Internet Explorer Browsers
        try{
            ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try{
                ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e){
                // Something went wrong
                die("Your browser broke!");
                return false;
            }
        }
    }   
    
    ajaxRequest.onreadystatechange = function(){
        if(ajaxRequest.readyState == 4){
            if(ajaxRequest.status == 200 || ajaxRequest.status == 304){
                
                var xml = ajaxRequest.responseXML;//!Important <-----------------
                var length = xml.getElementsByTagName("message").length; 
                    var last_msg = xml.getElementsByTagName("last_msg"); 
                for (i=0; i<length; i++)
                {   
                    var coolXML = xml.getElementsByTagName("message");
                    var name = coolXML[i].getElementsByTagName("content");
                    var id = coolXML[i].getElementsByTagName("user_id");
                    var msg_id = coolXML[i].getElementsByTagName("id")[0].firstChild.data;

                        var newmaindiv = document.createElement("div");
                            newmaindiv.id = msg_id; 
                            newmaindiv.style.cssText = "margin-top:5px;";
                        var newimage = document.createElement("img");
                            newimage.src = 'http://graph.facebook.com/'+id[0].firstChild.data+'/picture'; 
                        var newdiv = document.createElement("div");
                            newdiv.style.cssText = "display:inline;vertical-align:top;";
                            var newtxt = document.createTextNode(name[0].firstChild.data); 
                            newdiv.appendChild(newtxt);
                        document.getElementById("chatwindow").appendChild(newmaindiv);
                        document.getElementById(msg_id).appendChild(newimage); 
                        document.getElementById(msg_id).appendChild(newdiv); 
                }       
                    
                    document.getElementById("chatwindow").scrollTop = document.getElementById("chatwindow").scrollHeight;
                    document.getElementById("last_msg").innerHTML = last_msg[0].firstChild.data;
            start_timer(); //<-- Start timer just after last_msg is updated
            } else {
            die("Something Broke!");
            }
          }
      
    }   
    last_msg = document.getElementById("last_msg").innerHTML;                
    ajaxRequest.open("GET", "get_message.php?last_msg="+last_msg, true);
    ajaxRequest.send(null);
}     

function start_timer() {
setTimeout ("get_messages()",500); 

Sorry if I’m taking a while with this, it’s hard to debug ajax without a practical test and I don’t feel like creating a new database and hooking up a chat app right now :stuck_out_tongue:

Yes mate, that’s exactly what i have tried at first ;), it just won’t run that start_timer() function…
now it’s working fine tho when it’s at the beginning of that if statement.
I guess i’ll leave it that way for now and go more deeply into it later.
since now i am too tired and need to start working on chat rooms and private messages :smiley:

Yet, Thanks for your help :slight_smile:

No problem. It’s good to see that you’re working with raw javascript to get a grasp on the concepts, but before you go diving into making a larger scale application you may want to look into jQuery. It makes javascript development - especially ajax calls - extremely easy.

I am programming a lot with php, usually avoiding JS, but the best and quickest way to learn something is practice, that’s why i am trying to use JS as much as possible when i have the chance, even tho i am using Jquery as well.
Like you said, Jquery is much easier and more simple, that’s why i used it in order to perform an easier action, such as sending the message to the server using ajax.
I am using both to practice both :slight_smile: