SitePoint Sponsor

User Tag List

Results 1 to 11 of 11

Hybrid View

  1. #1
    SitePoint Enthusiast
    Join Date
    Apr 2007
    Posts
    69
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    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.

  2. #2
    SitePoint Addict Zarin Denatrose's Avatar
    Join Date
    Jan 2009
    Location
    Surrey BC, Canada
    Posts
    309
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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.

  3. #3
    SitePoint Enthusiast
    Join Date
    Apr 2007
    Posts
    69
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's what i am doing... sort of.
    My code currently looks like this:

    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){
                 ..... 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.

  4. #4
    SitePoint Addict Zarin Denatrose's Avatar
    Join Date
    Jan 2009
    Location
    Surrey BC, Canada
    Posts
    309
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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.

  5. #5
    SitePoint Enthusiast
    Join Date
    Apr 2007
    Posts
    69
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's what i've just explained when i did put the start_timer() at the end of the "bunch of code" inside onreadystatechange, it didn't run it at all.

  6. #6
    SitePoint Addict Zarin Denatrose's Avatar
    Join Date
    Jan 2009
    Location
    Surrey BC, Canada
    Posts
    309
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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...

  7. #7
    SitePoint Enthusiast
    Join Date
    Apr 2007
    Posts
    69
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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
    maybe it has something to do with the code itself, so here's the entire code:

    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);    
    }

  8. #8
    SitePoint Addict Zarin Denatrose's Avatar
    Join Date
    Jan 2009
    Location
    Surrey BC, Canada
    Posts
    309
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay, and you've tried this?
    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){
                    
                    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 :P

  9. #9
    SitePoint Enthusiast
    Join Date
    Apr 2007
    Posts
    69
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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

    Yet, Thanks for your help

  10. #10
    SitePoint Addict Zarin Denatrose's Avatar
    Join Date
    Jan 2009
    Location
    Surrey BC, Canada
    Posts
    309
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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.

  11. #11
    SitePoint Enthusiast
    Join Date
    Apr 2007
    Posts
    69
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •