Reputation: 33
I am working on a basic chatting service, it is basically a school project, and it is going to be used amongst students. I have been quite successful, however i have had one problem. Updating the chatroom. In many of my tests it tends to use up to 10 seconds for the message to be received, and recognized by the user that sent it.
It is all running php to push the messages to the chatfile and jquery to load that file. The chat is updated every 3 seconds. In my tests the chatfile gets updated instantly, however the actual chat does not update as fast, at an average of approximately 10 seconds.
i believe this must be some limiation in jquery. Should i move away from jquery and find a better solution, or is there something up about my code? Any help is greatly appreciated. Thanks in advance!
There is some php in there too, it is just to load a username and room name
Jquery code:
var roomname = "<?php echo $_GET["room"]; ?>";
var prevdata = "";
update();
setInterval(function(){update()},3000)
$("#send").click(function(){
sendMessage();
});
$('#message').keyup(function(e){
if(e.keyCode == 13)
{
sendMessage();
}
});
function update()
{
$.get("/rooms/room/"+roomname+".html",function(data){
$("#chatbox").html(data);
if(prevdata != data && data.indexOf("<?php echo $_SESSION["username"] ?>") != 31)
{
playMessageSound();
}
prevdata = data;
});
}
function sendMessage()
{
var message = $("#message").val();
$("#message").val("");
$.get("sendmessage.php?room="+roomname+"&message="+message)
}
function playMessageSound()
{
var audio = new Audio("/sound/msg.mp3");
audio.play();
}
My solution: I took jwatts' solution and customised it a bit to make it in fewer lines of code. i now just compare the chat, to the file, and return the differences, appending those to the chat, making it as fast as the update can go!
Thanks for the help guys!
Upvotes: 3
Views: 1813
Reputation: 7356
I know this question has been answered, but I wanted to throw in another possible solution. It is, as these things go, a simple one with some catches and caveats, but for a class project it would suffice. The example I am proposing is not one that I have created myself, and the code is untested. And it would likely take you a fair bit of time to implement the changes and get them to work.
But it explores some basic data formats such as the XML and JSON capabilities in PHP and JavaScript. It keeps track of the most recent data grab and only gets the new chat information. This way once the data gets back to the browser, it's only loading the new stuff instead of the whole thing.
In your code above, it looks like you are writing the entire chat, each time. I am sure there is some browser caching issue going on. Rather than requesting the entire html page each time, you could request a PHP that returns JSON data (PHP has built-in JSON functions) that only includes the last entries, and you append those to the document.
There is a lot of information available on JSON. If you haven't learned about it yet, it is a way of expressing data that is native to JavaScript. It can natively convert JSON formatted text into arrays, objects, and properties. And it is not as verbose as XML.
In your code, create a time stamp called
var lastDataReceived = "";
This will keep a time stamp of the last time new chat data was received from the server. In the $.get()
success function, change the URL to a PHP page and set it to get JSON data. Also, pass in the needed information such as the name of the room you need data from, and the last time chat data was received:
function update()
{
$.get({
url: "/rooms/room/getchatdata.php",
data: { "room": roomname, "lastDataReceived": lastDataReceived },
success: function(data){
//..............
},
dataType: "json"
});
}
This will create a request to
"/rooms/room/chatdata.php?room="+roomname+"&lastDataReceived="+lastDataReceived
On the server side, you can get the querystring parameters like so
$roomname = $_GET["room"];
$lastDataReceived = date_create_from_format('d/M/Y H:i:s', $_GET["lastDataReceived"]);
It looks like you are writing chat information to an HTML file. In this example, using XML data would most likely be preferable. There are many, many PHP XML tutorials out there. Here is one at W3Schools.com for SimpleXML functions. (http://www.w3schools.com/php/php_ref_simplexml.asp)
With this you can load from a file:
$xml = simplexml_load_file($roomname.".xml");
You can also create a new XML file if it is a new room for example:
<?php
$chats = <<<XML
<chats>
</chats>
XML;
$xml = new SimpleXMLElement($chats);
$xml->saveXML($roomname.".xml");
?>
To determine whether to read or write, you can check if the room exists by checking if the file for that room exists:
$xml = NULL;
if (file_exists($roomname.".xml")) {
//Set to exsiting
$xml = simplexml_load_file($roomname.".xml");
} else {
//Create new file
$chats = <<<XML
<chats>
</chats>
XML;
$xml = new SimpleXMLElement($chats);
$xml->saveXML($roomname.".xml");
}
Either way you get a $xml
variable that you can work with.
So now, say you've made your request back to the server to see if there is any new chat data. You're working with the variables $roomname
and $lastDataReceived
that you created earlier. And you've loaded the $xml
object from the file. Now you need to find any new additions.
$chats = $xml->chats->children();
$newchats = array();
foreach($chats as $c) {
if ($c['date'] > $lastDataReceived) {
array_push($newchats, $c);
}
}
Now that you have an array of the new chat items, write the JSON data back to the browser:
$json = json_encode($newchats);
header('Content-Type: application/json');
echo $json;
Now back to your JavaScript. In the PHP sample above, $newchats
is initialized as a new array. When json_encode()
is called on it, if there are no new chats, the echo
will return an empty array. You can test for this in JS.
In this case, you would only be adding the new items that came in. So you would need to add new HTML to the document. This is super easy with jQuery. Say the chats were all in a <div>
tag:
<div id="chats">
<!--all chats here-->
</div>
And you have a template div
that you want all chats to look like
<div class="chat_template" style="display:none;">
<div class="person_name"></div>
<div class="chat_text"></div>
<div class="chat_time"></div>
</div>
You can clone it, load the data into it, and append it to the document.
function update()
{
$.get({
url: "/rooms/room/chatdata.php",
data: { "room": roomname, "lastDataReceived": lastDataReceived },
success: function(data){
if (data.length > 0) {
for (var i = 0; i < data.length; i++) {[
var c = data[i];
//I do not know what the exact structure of the data will be.
// You may need to output the data to the console to see it's structure.
// But I am assuming you will have access to the date value, the person's name
// and the text.
//Clone the template and add the values
var div = $("div.chat_template").clone(true);
div.find("div.person_name").html(name);
div.find("div.chat_text").html(text);
div.find("div.chat_time").html(date_val);
div.show();
//Add the new div to the document
$("div#chats").append(div);
//Set the last received time for the next query
lastDataReceived = date_val;
}
playMessageSound();
}
},
dataType: "json"
});
}
When sending new chat info to the server, you can use that same data: { "chattext": text....}
type structure in the jQuery $.post()
function. You will need a different PHP file on the server like addchatdata.php
. I already touched on an algorithm which gets or creates a chat room file based on whether it exists.
So if you want the child XML element to look like this
<chat date="04/Jun/2015 13:18:23" name="George">
Here is some of George's text.
</chat>
Once you get the $xml
object, you can add new XML to it like so:
$chat = $xml->addChild("chat", "Here is some of George's text.");
$chat->addAttribute("date", date('d/M/Y H:i:s'));
$chat->addAttribute("name", "George"); //<--Or use a variable name for the name
//Then save the changes back out to the file:
$xml->saveXML($roomname.".xml");
In a general sense, this is doing what you were already doing: storing data from new chats, then loading that data into other clients connected to the chat. However, here it is only retrieving the new information, and will load much faster on the browser.
Upvotes: 4
Reputation: 1839
From what I can tell you have the general understanding of how the scripts work, and the overall general concept of what you want to do. Which is good.
As far as making your application faster. There's not a whole lot that can be done there with the way it is currently built. The best you can do is look at the speed of any loops you have and check that they are not too in depth as that can overclock processes and decrease the speed at which data is retrieved from the server.
JSF Methods
I have been researching JSF (JavaServer Faces), which is a J2EE framework for server based applciations. It implements CSS, HTML, and various components of other languages and from what I can tell is extremely versatile. Depending on what types of languages you can use, and if you have at least basic knowledge of the aforementioned languages along with Java then I would recommend looking into it.
http://www.tutorialspoint.com/jsf/index.htm
If you want a faster overview I also found the wikipedia page to be helpful as well.
http://en.wikipedia.org/wiki/JavaServer_Faces
socket.io and node.js
This is something far more entertaining that I have discovered as well, I don't know why I wasn't thinking of it earlier when I answered this question. This uses the new features of websockets in html5 for nice responsive pages. A lot easier and cleaner to use, and it goes right along with what you are trying to do.
Here is all the stuff I've been using, if you have questions about it please don't hesitate to comment on here and I will try and get you more info
https://www.youtube.com/watch?v=pNKNYLv2BpQ
This is a very good tool and I recommend this over JSF any day.
Upvotes: 1