-1

I made a chat program, which is working fine except now, I need to add Ajax to the program to refresh the chat log every one second. The AJAX is supposed to call the function to grab data from the database every second so that if another person sends a message it will show up onto the chat log without having the user refresh the page. The name of my file is index.php:

Here is Ajax I have so far, which is not working: This is inside the head tag.

  <script>
         $(document).ready(function()
         {
         new refreshChat(); 
         });
              
         function refreshChat()
         {
                var x = $.ajax({
                    type: "POST",
                    url: "index.php",
                    data: {action: 'refresh'},
                    async: false,
                    success: function(output) {
                      alert(output);
                  }
                }).complete(function(){
                    setTimeout(function(){refreshChat();}, 1000);
                }).responseText;
            
                $('div.chat_data').html(feedback);
         
              }
 </script>

Now, here is my PHP function to get data from the database (NOTE: I have no issues connecting to my database, so the PHP function should not be a problem with my program:

  function refresh()
          {
              global $dbc;
             
              $query2 = "SELECT `name`, `message` FROM `chatApp`";
              
              $run2 = $dbc->query($query2);
              
              while($row = $run2->fetch_assoc())
              {
              
                echo "<p>" . $row['name'] . ": " . $row['message'] . "</p>";
                
              }
            
          }
Dharman
  • 30,962
  • 25
  • 85
  • 135
Wash Hands
  • 11
  • 3
  • where and how are you using the `refresh()` method? – Funk Forty Niner Apr 20 '18 at 13:03
  • @FunkFortyNiner I had the refresh method stored inside my chat log div. I am new to Ajax so is `data: {action: 'refresh'}` the right way to call the php `refresh()` method? – Wash Hands Apr 20 '18 at 13:04
  • Where does `feedback` come from exactly? – jeroen Apr 20 '18 at 13:07
  • 1
    I don't know JS like some of the others guys here but I doubt you can do that. – Funk Forty Niner Apr 20 '18 at 13:07
  • @FunkFortyNiner I tried doing something simple like this, but still doesn't work: `$(document).ready(function() { setTimeout(function(){ new refreshChat(); },1000); }); function refreshChat() { refresh(); }` – Wash Hands Apr 20 '18 at 13:16
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Wash Hands Apr 20 '18 at 14:21

3 Answers3

0

You can use setInterval to refresh every second

Thomas Durand
  • 46
  • 1
  • 10
0

Your ajax call is not structured correctly, it should be:

$.ajax({...}).done(function(feedback){
 $('div.chat_data').html(feedback);
 setTimeout(refreshChat, 1000);
});

This way you first populate chat and then make another call, so that a new call is not made, before another is complete.

EDIT: you should use .done instead of .complete since .complete is deprecated for jquery 3.0 to resolve your ajax promises.

jacobdo
  • 1,605
  • 3
  • 15
  • 34
0

I highly suggest not using synchronous AJAX calls, but instead setting a short timeout on each request and using setInterval() instead of using setTimeout(). The whole point of AJAX is that it's supposed to be asynchronous. That way, your script can continue to do something else while it waits for the response to come back from the server, instead of being unresponsive for however long that takes.

Second, you're kind of suffering from a Schlemiel the Painter problem. With each request (every second) you're sending the entire chat log over the internet, while a chat's history doesn't actually usually change. It'd be far more efficient to only send any new messages posted in the chatroom.

Try modifying the PHP script to send some JSON data back as an object. Let's start simple, and create an object like so, assuming $log holds the last few chat messages, and $lastID holds the last message's ID. Your SQL query will look something like:

SELECT `name`, `message` FROM `chatApp` WHERE ID > ?

Where the parameter is filled with the last ID submitted by the javascript. (Don't forget to use stored parameters, as the user is not to be trusted).

Don't forget to set the correct message header:

$response = new \stdClass();
$response->changes = $log;
$response->messageID = $lastID;
header("Content-Type: text/json");
echo json_encode($response);

Try modifying the javascript program to call a routine like this every second:

$.ajax({
    type: "POST",
    url: "index.php",
    data: {
        lastMessageID: lastID
    }
}).done(function( response ) {
    $('div.chat_data').append(response.changes);
    lastID = response.messageID;
}); 

Now we're not entirely there yet. When the request takes longer than a second, you can get some race conditions. What you should then do is wrap each chat message in its own element (e.g. a <div> seems most appropriate), and send the chat messages that were changed back as an array.

Using PHP's associative arrays, you could use the ID of the database row as the array key, and put the whole array into the $log variable. It would be readable on the javascript side as response.changes[<N>] where <N> is some element ID. Iterate over the members of response.changes, then skip any messages that were already present.

In order to store the ID in the DOM, you could use something like:

<div class='chat_message' data-id=576><p>Hello World!</p></div>

To represent a chat message. You can then quickly find any messages that match your response. You could also use jQuery's element storage, or use a variable specific for your chatapp object to cache the currently displayed message IDs.

aphid
  • 1,135
  • 7
  • 20