0

I've looked some AJAX threads looking for my problem, but I didn't find a solution for my case. Here's the thing:

I have a page with user comments. Those comments are saved in a database and every time the user press a "Refresh" button there's a connection to the database, getting the comments in response. If there are any new messages, there's a div "There are _ new messages". However, this last message never shows up properly, because it appears before the messages are loaded.

Here's the code:

AJAX function

function GetComments()
{
    $("#cont-comment").empty(); //div that contains the messages
    $.ajax(
    {
        url: "get.php",
        dataType: "json",
        success: function(data)
        {
            n_msg=data.length;
            for (i=0; i<n_msg; i++)
            {
                nick=data[i].nick;
                msg=data[i].msg;
                WriteNewComment(nick,msg);
                num_comments=document.getElementsByClassName("comment-msg").length;
            }
        } 
    });
}

And here's the problem.

$("#refresh").click(function()
{
    num_comments_before=num_comments;
    GetComments();
    alert("done");
});

The "done" message appears before the new comments. I would like that the message "done" only would appear when the new comments show up - when AJAX has finished.

SBD
  • 446
  • 6
  • 17
Alfall
  • 11
  • 2

4 Answers4

0

Since ajax is an asynchronous call, browser spawns a thread as soon as you make an ajax call and continues its flow, that's why your "done" message appears before the new comments. Ideally you should not block your code unless it is a strongly required.

You can call alert('done') function in the call back as shown below...

 function GetComments(alertFunction)
{
    $("#cont-comment").empty(); //div that contains the messages
    $.ajax(
    {
        url: "get.php",
        dataType: "json",
        success: function(data)
        {
            n_msg=data.length;
            for (i=0; i<n_msg; i++)
            {
                nick=data[i].nick;
                msg=data[i].msg;
                WriteNewComment(nick,msg);
                num_comments=document.getElementsByClassName("comment-msg").length;
            }

          **alertFunction();**
        } 
    });
}



$("#refresh").click(function()
{
    num_comments_before=num_comments;
    GetComments(alertFunction);

});

function alertFunction(){
  alert("done");
}
Bala
  • 1,295
  • 1
  • 12
  • 23
0

Although jQuery doesn't properly adhere to the Promises/A spec, the $.ajax() method returns a deferred object which you can utilise to handle your response logic. Here's one way it could work:

$.when(getComments).then(processComments);

function getComments() {
    $("#cont-comment").empty();
    return $.ajax({
        url: "get.php",
        dataType: "json",

    });
}

function processComments(data) {
    n_msg=data.length;
    for (i=0; i<n_msg; i++) {
        nick=data[i].nick;
        msg=data[i].msg;
        WriteNewComment(nick,msg);
        num_comments=document.getElementsByClassName("comment-msg").length;
    }
    alert("done");
}

Doing things synchronously is not generally regarded as best-practice when it comes to JavaScript, and the callback approach is OK but it suffers from multi-nesting madness and troublesome error handling.

Ian Clark
  • 9,237
  • 4
  • 32
  • 49
0

The above comments are correct. You need to do your updating in the callback. A couple of call outs about your code. You should always var your variables. Not doing so, in javascript, adds the variables to the global scope (which is bad!). Also, it is best to use K&R style braces (opening on same line not on new line) as using Allman style can sometimes cause issues. link to article

If you want to use a more modern approach then I recommend using jquery $.when and .done() for your ajax calls.

$.when(GetComments()).done(function(data){
  var n_msg = data.length, i=0, nick, msg, num_comments=0;
  n_msg = data.length;
  for (; i<n_msg; i++) {
    nick = data[i].nick;
    msg = data[i].msg;
    WriteNewComment(nick,msg);
    num_comments=document.getElementsByClassName("comment-msg").length;
  }
  alert('done');
});
Gary Storey
  • 1,779
  • 2
  • 14
  • 19
  • here is the link to the jquery api docs on `$.when`: http://api.jquery.com/jQuery.when/ – Gary Storey Sep 02 '14 at 18:33
  • Thank you! I didn't know anything about $.when. Looks like a great choice. And I also appreciate your tips about variables (I know, my bad) and style braces. – Alfall Sep 02 '14 at 21:02
-1

If you add:

async: false

to your ajax call, your javascript will wait for the ajax function to return (success or error) before continuing.

http://api.jquery.com/jquery.ajax/

dkoepp
  • 1
  • 2
  • Use of async has been deprecated and discouraged, instead one should use callbacks. – Bala Sep 02 '14 at 17:39
  • That worked, thanks! Bala, I also appreciate your response. When I'll have it all running, I'll use your option. Thank you very much. – Alfall Sep 02 '14 at 17:48