0

I'm building a chat page for members of one of my websites. Everything works properly for me, except for the chat's automatic updates. The chat page is supposed to check for new messages every 5 seconds, and manipulating the callbacks shows that this part is working correctly; however, the PHP file that $.ajax references is giving me two very different behaviors. Because the ajax is working correctly in every test I have performed, I will exclude it here, but I can add it if anyone feels it is necessary. This is my annotated PHP:

$new_chat = //new chat message, collected from $.ajax and sanitized
$new_sender = //username of sender, collected from $.ajax and sanitized
$new_time = date('m-d-y');
$most_recent_chat = //unique id# of most recent chat message, collected from $.ajax and sanitized

//This block makes sure that there is a most recent chat; if not, (i.e., the
//page was just loaded so there are no chats on the page) it manually sets one.
//I'm not having any problems with this block.

if (!isset($most_recent_chat)) {
    $query = "SELECT MAX(id) AS 'Most Recent' FROM `chat_global`";
    $check_last_chat = new mysqli($host,$user,$pass,$game_db);

    $check_last_chat->query($query);

    if(!$result = $check_last_chat->query($query)) {
        die();
    }

    while ($row=$result->fetch_assoc()) {
        $most_recent = $row['Most Recent'];
    }
    $most_recent_chat = $most_recent-100;
    $result->free();
    $check_last_chat->close();
}

//Send any new chats to DB

if(isset($new_chat)) {
        //First query inserts new chats into the chat table
        $query = "INSERT INTO `chat_global` (message,sender,time) VALUES ('".$new_chat."','".$new_sender."','".$new_time."');";

        $add_new_chat = new mysqli($host,$user,$pass,$game_db);

        $add_new_chat->query($query);
        $add_new_chat->close();

        //Second query returns all new chats in reference
        //to the most recent chat on the user's browser page

        $query2 = "SELECT * FROM `chat_global` WHERE id>'$most_recent_chat';";

        $most_recent_chats = new mysqli($host,$user,$pass,$game_db);

        if(!$result = $most_recent_chats->query($query2)) {
            die();
        }

        while($row = $result->fetch_assoc()) {
            echo '<div class="chat-item" data-chat-id="' . $row['id'] . '">';
            echo '<p class="chat-message"><strong>' . $row['sender'] . ': </strong>' . $row['message'] . '</p>';
            echo '<p class="chat-time">' . $row['time'] . '</p></div>';
        }

        $result->free();
        $most_recent_chats->close();
} else {
    //Query 2 from above is repeated; basically, skips adding new message
    //and simply retrieves any other new messages
    $query2 = "SELECT * FROM `chat_global` WHERE id>'$most_recent_chat';";

    $most_recent_chats = new mysqli($host,$user,$pass,$game_db);

    if(!$result = $most_recent_chats->query($query2)) {
        die();
    }

    while($row = $result->fetch_assoc()) {
        echo '<div class="chat-item" data-chat-id="' . $row['id'] . '">';
        echo '<p class="chat-message"><strong>' . $row['sender'] . ': </strong>' . $row['message'] . '</p>';
        echo '<p class="chat-time">' . $row['time'] . '</p></div>';
    }

    $result->free();
    $most_recent_chats->close();
}

The if(isset($new_chat)) block is simple and it's not giving me problems. Basically, if there is a new message, it adds the new message to the chat database and then returns all messages with ID numbers higher than the most recent from the browser's point of view. This part works and returns its information to the browser within 1/4 second.

The else block in this code is where I seem to be having some problems. The else block is the same, line for line, as the second half of the if block (from $query2 down). It works, but very slowly; whereas the if block loads from the server in 1/4 second on average, the else block (which is less code) takes an average of 90 seconds to return data. The $.ajax call is the same function whether a user sent a message or not; the only difference is that the if block is referenced if a user sent a message (and the $.ajax call is therefore manual), but the else block is referenced automatically by a repeated setTimeout(function,5000) line in the browser.

I'm 99.9% certain that the setTimeout() is working properly, because if I manually set my $.ajax call to send a generic $new_chat (i.e., "This is a message.") the function works every time; every 5 seconds, it sends the chat, and 1/4 second later, I see it appear in my chat page as expected. (My chat page is populated fully by the above PHP; even messages sent from user A must be sent to the above file, processed, and sent back to user A, that way users can know that their message was sent.)

The bottom line is that I'm at a complete loss as to why this behavior is occurring. The $.ajax is in the same function whether it's automatic or manual; the PHP is the same code, and the slower block is also shorter to boot! The $.ajax call runs perfectly quickly when it's manual, and if a message is sent along with the automatic $.ajax it also runs perfectly quickly. I'm new to AJAX and jQuery so I would like to think that the problem lies with one of those technologies, but nothing makes sense at all from where I'm sitting.

  • How do you know you it's the request that is taking a long time. Do you see a 90 second delay in the network tab of your browser developer tools? Can you `console.log` something before the request and after the request to really see it's the php request that is failing? Since you a using polling you should see the requests in your network tab and how long each one takes. – Leeish Jun 02 '16 at 22:11
  • Have you tried removing everything in the `else` block and just putting: `echo "test";` to see if that also takes 90 seconds? – Bradley4 Jun 02 '16 at 22:15
  • I just added console.log('Before ajax') at the top of my JS function and console.log( 'After ajax') in the success callback. They are both logged every five seconds, like clockwork...but new chats are not delivered for several minutes still. I look in the database with phpMyAdmin and they are there; they just aren't getting collected in a timely manner.... – Christian Speegle Jun 02 '16 at 22:21
  • @Bradley4 just putting "echo 'test';" results in perfect loadtimes too, every 5 seconds – Christian Speegle Jun 02 '16 at 22:28
  • @Leeish also, no there is not a 90 second delay in the network tab; messages simply aren't arriving for 90 seconds. It shows that the request transferred about 130 bytes (transferring in HTML, not JSON) and the transfer took 203 ms. The check itself is performed 5 seconds after each request ends, which is as expected with the setTimeout(). I send a chat in one browser and it appears instantly in the database according to phpMyAdmin, but my other browser does not receive the message for anywhere from 30 seconds to five minutes. – Christian Speegle Jun 02 '16 at 22:42
  • Maybe the result of your SELECT query is being cached by MySQL? http://dev.mysql.com/doc/refman/5.6/en/query-cache-in-select.html – jpec Jun 02 '16 at 23:16
  • If what you are saying is true then I suggest doing the following. Setup a page that you can simply refresh and it will dump the table contents or the last row(s) in the table, whatever. Add data via whatever method you want and refresh that new page. See how long it takes for your new data to appear. Sounds like it may be caching either the query, the JSON call, the html result, etc. Something seems to be cached if your calls are in fact executing and returning data without a delay. – Leeish Jun 06 '16 at 17:48

0 Answers0