I've search internet for days to find an optimized solution for having a live collection in backbone.js. think of a virtual room (e.g chat room) and I wanted to show who is in that room. right now I fetch collection each 2 sec and add new user (in my case player) to the list view, and it's working but I'm afraid of traffic and all of those useless ajax request that return nothing.
here is my backbone scripts:
App.players = new App.Collections.Players;
waitingUserList = new App.Views.WaitingPlayers({ collection: App.players });
setInterval(function() {
App.players.fetch({
success: function(collection) {
collection.each(function(player) {
if (player.get('added') == 0) {
player.set('added', 1);
player.save();
}
});
},
});
}, 2000);
$('div.waiting-list').append(waitingUserList.el);
and my php code (I'm using laravel 3):
public function get_index($gid)
{
$players = Game::find($gid)->players()->get();
if (!empty($players)) {
return Response::eloquent($players);
} else {
return false;
}
}
Is there any way that, when collection.fetch() called, it wait until some new record added to database, and then server respond to ajax request.
P.S. I don't want to use html5 websockets
P.S.S. this is my first backbone experience, so forgive me if I've been mistaken somewhere or said something foolish :D
thanks in advance
What you are doing is called polling. As you already mentioned, it doesn't scale very well. You should search for a comet like solution. It all depends on your backend. For example Apache doesn't do very well in this regard (Using comet with PHP?).
Depends on your needs, but I would recommend node.js and socked.io which implements web sockets and a fallback for older browsers. If you want to interact with your existing code use proxy on your main web servers.
Related
I am actually developing application for bank cash management.. It must be real-time... Once there is a change in db it must be sent to the client... I don't want to use long polling or ajax etc... (Because It puts load on the server by repeating requests)...
Cant use nodejs or other server related technology... (Not installed in server)... Question is that I want to develop server pure in php... Can anyone post code and give the details about it... Searched internet a lot but nothing there... Suggestions will be appreciated
[Edit]
I am putting my angularjs code for long polling here:
function dataCtrl($scope, $timeout, Data) {
$scope.data = [];
(function tick() {
$scope.data = Data.query(function(){
$timeout(tick, 1000);
});
})();
};
and I call tick function in the following code
$http.get('url').success(function(data, status, headers, config) {
data.response = data;
$('.serverStatus').text(data.response.message);
data.calls++;
$timeout(poller, 1000);
});
};
You must use sockets in your application... You can find Php socket library named Rachet over here
http://socketo.me/
There must be socket connection between users. So socket will listen until the data comes
I'm a newbie web developer diving into Backbone for the first time. One major question I've been grappling with (actually spending a lot of the last 2 days researching to no avail) is how exactly Backbone communicates with the server.
In my previous projects, I've been able to fetch data from my database using PHP and jQuery's $.getJSON method. I'm also able to do this when I use Backbone (ex. myCollection.url = "todos.php"). However, in every single tutorial, documentation, example code I've looked at, the url for the collection is always set as a directory and the urlRoot is directory/id (ex. myCollection.url = "/todos" and myModel.urlRoot = "/todos/5".
My question is how exactly is this managed? It seems a lot cleaner than the traditional way I was doing by adding GET parameters to my calls. At first I thought this was routing, but that seems to be only related to setting browser history and stuff. Some of the source code I've looked at uses SLIM PHP and Rails (neither of which I've used) but I have no clue how any of the parts fit together.
Backbone has its own api for communicating with server, such as fetch, save, destory.In fact, these methods do the same things with jQuery's $.ajax. For example, you use backbone's fetch in this way:
var UserModel = Backbone.Model.extend({
url : "rootURL/user",
});
var user = new UserModel;
user.fetch(
data:{
userId : 1, //the webservice will be: rootURL/user?userId=1 GET;
}
success:function(model, response, options){
//callback
},
error:function(model, response, options){
//callback
},
);
But you can also use the same way as in the jQuery to communicate with server in backbone's application.For example:
var UserView = Backbone.View.extend({
render: function(){
//do something
}
getUser: function(userId){
$.get("rootURL/user",
{ userId : userId},
success:function(data){
//callback
}
);
}
});
I have seen this question before and found this example in http://www.zeitoun.net/articles/comet_and_php/start which is really great and clear. However, it uses javascript.
My question is, are there any plugins, functions or something that would help me to implement PHP comet with jQuery easily? Because given example requires lots of javascript code.
And by the way, I want to use it on Apache. Is it possible?
If you are only doing long polling then jQuery will work fine. However, jQuery does not expose a readyState === 3 event, so there is no built in way to get data as it is streaming if that is the direction you want to go.
[Edit]
Here is the bug, #1172
And it looks like they added the functionality in 1.5, using a Prefilter
So yes, you can do all the comet stuff with jQuery now :)
Comet is long-polling where client sends a request and waits for the response from the server. The server queues the request and once it gets the updated results. It sends the response to the client.
So basically all you need to do is to send an .ajax request to the server and use the onSuccess callback to deal with the returning the data. The onSuccess callback will not be called unless the server gets the updated data.
Nothing really fancy at the client-side. The actual game is on the server side to queue the requests and then respond accordingly.
Take a look at this answer detailed code sample > How do I implement basic "Long Polling"?
i have made the jQuery version of comet before, this is what i had done:
var comet = {
connection : false,
iframediv : false,
initialize: function(){
// For other browser (Firefox...)
comet.connection = $('<iframe>');
comet.connection.attr('id', 'comet_iframe');
comet.connection.css( {
left : "-100px",
top : "-100px",
height : "1px",
width : "1px",
visibility : "hidden",
display : 'none'
})
//comet.iframediv = $('<iframe>');
comet.connection.attr('src', 'backend.php');
//comet.connection.append(comet.iframediv);
$('body').append(comet.connection);
},
// this function will be called from backend.php
printServerTime: function (time) {
console.log('time',time);
$('#content').html(time);
},
onUnload: function() {
if (comet.connection) {
comet.connection = false; // release the iframe to prevent problems with IE when reloading the page
}
}
}
$(window).load(comet.initialize)
.unload(comet.onUnload);
i had taken the code right off that page and made it jquery ^_^
there is a plugin i have seen, try this? http://code.google.com/p/jquerycomet/
I am working on using node.js's connection abilities to continiously long poll a php script and I was wondering if anyone knows the thoery behind (maybe even a code sample) linking to php in node.js? I was thinking I need a new client and I add a request for the php page and then I add a response event listener which then fires off a event function which grabs the returned data and throws it back into the server function.
I am, however, a noob and need some initial guidance since their api documentation is not the easiest to read; the English is too wordy and it's white font on a dark background...not nice.
Thanks,
var sys = require('sys'),
http = require('http'),
url = require("url"),
path = require("path"),
events = require("events");
var twitter_client = http.createClient(80, "192.168.23.128");
var tweet_emitter = new events.EventEmitter();
function get_tweets() {
var request = twitter_client.request("GET", "/?url=ajax/session", {"host": "192.168.23.128"});
request.addListener("response", function(response) {
var body = "";
response.addListener("data", function(data) {
body += data;
});
response.addListener("end", function() {
sys.puts(body);
var tweets = JSON.parse(body);
if(tweets.length > 0) {
tweet_emitter.emit("tweets", tweets);
}
});
});
request.end();
}
setInterval(get_tweets, 5000);
http.createServer(function (req, res) {
sys.puts("accessed Server");
res.writeHead(200, {'Content-Type': 'text/plain', "Access-Control-Allow-Origin": "*"});
var t = JSON.stringify({id:"test"});
var listener = tweet_emitter.addListener("tweets", function(tweets) {
res.write(tweets);
});
res.write(t);
res.end();
}).listen(8124);
sys.puts('Server running at http://127.0.0.1:8124/');
This seemed to work. Taken from a mixture of other tutorials
Was just doing some research on this topic, and wanted to drop in an answer for anyone that might be looking to do the same thing.
The comments on the OP made good points as to whether or not this sort of thing would be an efficient use of resources, or a waste of nodes event-based processing abilities. I would say that passing requests on to an Apache/PHP server would be inefficient, because you're essentially doing the same thing as having recurring AJAX request sent to the Apache server. The only difference is you now have a man-in-the-middle sending the requests.
Apache is still serving requests just the same as it always is, it is just serving them to the Node.js server rather than the client. This does not build in any efficiencies, other than taking a bit of load off the client and placing it on the server.
The correct way to do this, as #Paul mentioned, is to use some sort of PHP processor that will allow you to bypass Apache. There's some fancy methods for getting this done using FastCGI and PHP-FPM - they're pretty high level so you might have some trouble integrating them into Node.js on your own.
On the bright side, there's a node module already being built to do just this: node-php. It's pretty young ("omega-alpha-super-beta-proof-of-concept"), but may be able to handle what you're trying to do. If it can't, at least it's a good starting point, and you can fork off to make your own additions
In the project I am currently working on, we have the need to develop a web chat application, not a very complex chat, just a way to connect two people to talk about a very specific topic, we don't need any kind of authentication for one of the two users, we don't have to support emoticons, avatars, or stuff like that.
Some project members suggested that we could use XMPP through BOSH, I said that is like trying to catch a fish with a boat's net, and proposed a simpler method, like a simple Ajax/MySQL web chat, but we're worried about the performance hit in the server because of the constant polling of many chats open at the same time.
Has anyone done something like this before? What would you recommend?
You might also want to look into Comet.
It's used by GTalk, Meebo, and many other chat applications. A few years ago when I was experimenting with it, there weren't very many libraries or details about server architecture to implement it, but it looks like there is a lot more stuff out now.
Have a look at the cometd project for more technical information.
What would you recommend?
XMPP through BOSH
There's no need to invent your own message format and transport protocol when somebody else has. If you try, it'll slowly grow to be just as complex as BOSH but without the benefit of third-party library support or standardization.
If you don't like the idea of HTTP-polling, you could have a Flash-movie on the chat page that has a constant connection to some deamon on the server, the Flash-movie would then invoke JavaScript functions on the client to update the chat as new messages comes along. (Unless you want a Flash interface for your chat..)
You might also want to look into Comet.
I thought everyone used cometd for this sort of thing.
BOSH is a standard for transporting XMPP over HTTP. It involves Comet for pushing data to the client.
There is a very good server for handling message pushing from server to browser (dubbed Comet) - Orbited. It's easily integrated with other technologies (Django, Rails, PHP etc.) just like memcached.
You really should check it if you want to handle serious load. Otherwise, simple Ajax polling is the best way.
The trick is to realise that the only time your app needs to invoke CGI on the server is when someone says something. For the regular polls, poll a static page that your CGI script updates whenever there is new chat. Use HEAD requests, compare the timestamps with those last seen, and only do a full GET when those change. I have a simple naive chat application implemented this way, and the load and bandwidth usage is negligible for the few tens of simultaneous users we have.
I did this very same thing a few months back and had fun just playing around with the concepts. I actually used the forever-frame technique instead of polling.
The below code is my "comet" js file that contains the general concepts required to get a "party chat" setup.
function Comet(key) {
var random = key;
var title = 'Comet';
var connection = false;
var iframediv = false;
var browserIsIE = /*#cc_on!#*/false;
var blurStatus = false;
var tmpframe = document.createElement('iframe');
var nl = '\r\n';
this.initialize = function() {
if (browserIsIE) {
connection = new ActiveXObject("htmlfile");
connection.open();
connection.write("<html>");
connection.write("<script>document.domain = '"+document.domain+"'");
connection.write("</html>");
connection.close();
iframediv = connection.createElement("div");
connection.appendChild(iframediv);
connection.parentWindow.comet = comet;
iframediv.innerHTML = "<iframe id='comet_iframe' src='./comet.aspx?key="+random+"'></iframe>";
} else {
connection = document.createElement('iframe');
connection.setAttribute('id', 'comet_iframe');
iframediv = document.createElement('iframe');
iframediv.setAttribute('src', './comet.aspx?key='+random);
connection.appendChild(iframediv);
document.body.appendChild(connection);
}
}
// this function is called from the server to keep the connection alive
this.keepAlive = function () {
if (!browserIsIE) {
mozillaHack();
}
}
// this function is called from the server to update the client
this.updateClient = function (value) {
var outputDiv = document.getElementById('output');
outputDiv.value = value + nl + outputDiv.value;
if (blurStatus == true) {
document.title = value;
}
if (!browserIsIE) {
mozillaHack();
}
}
this.onUnload = function() {
if (connection) {
// this will release the iframe to prevent problems with IE when reloading the page
connection = false;
}
}
this.toggleBlurStatus = function(bool) {
blurStatus = bool;
}
this.resetTitle = function() {
document.title = title;
}
function mozillaHack() {
// this hack will fix the hour glass and loading status for Mozilla browsers
document.body.appendChild(tmpframe);
document.body.removeChild(tmpframe);
}
}
I thought everyone used cometd for this sort of thing.
I agree with John. But there was another question that was not answered.
I have done this but instead of using a database we used a flat file, it did eventually cripple the server, but it wasn't until we has ~450 active users, and if we had done it with a database it probably would have fared better.This was done on a basic hosting account from Godaddy.
Edit: BTW Godaddy sounded less then amused when I got the phone call.
I think polling is the simplest approach and would recommend that first. If the load becomes a problem start, looking into more complicated techniques.
A good discussion on the pros and cons are here -
http://www.infoq.com/news/2007/07/pushvspull
http://ajaxian.com/archives/a-report-on-push-versus-pull
Checkout Speeqe. Its a open-source solution for Web-based chat rooms that uses BOSH and XMPP behind the scenes.
I just found this post, it is old, but polling concept gives troubles for a lot of poeple. So i'll put an implementation example here. But before giving it to you, I should give you an advice that made me mad some time ago :
When you poll, you should take care of sessions behaviour (race conditions). To make it simple : if you open a session, the session file is locked until the session is closed to avoid 2 theads writting different data into it. So, if you need a session to check if a user is logged or so, always close the session before polling.
My demo gives you an example of a polling implementation in PHP. I will not use a database, but a file instead. When you click polling button, you will enter the loop and until the file is modified, you will stay polling. When you fill the form and click Release, what you typed will be saved into the file. Modification time of the file will change so the polling will stop.
Tip: use a tool like Firebug to see what's happen.
Now lets speak in a better langage than my english :
<?php
// For this demo
if (file_exists('poll.txt') == false) {
file_put_contents('poll.txt', '');
}
if (isset($_GET['poll'])) {
// Don't forget to change the default time limit
set_time_limit(120);
date_default_timezone_set('Europe/Paris');
$time = time();
// We loop until you click on the "release" button...
$poll = true;
$number_of_tries = 1;
while ($poll)
{
// Here we simulate a request (last mtime of file could be a creation/update_date field on a base)
clearstatcache();
$mtime = filemtime('poll.txt');
if ($mtime > $time) {
$result = htmlentities(file_get_contents('poll.txt'));
$poll = false;
}
// Of course, else your polling will kill your resources!
$number_of_tries++;
sleep(1);
}
// Outputs result
echo "Number of tries : {$number_of_tries}<br/>{$result}";
die();
}
// Here we catch the release form
if (isset($_GET['release']))
{
$data = '';
if (isset($_GET['data'])) {
$data = $_GET['data'];
}
file_put_contents('poll.txt', $data);
die();
}
?>
<!-- click this button to begin long-polling -->
<input id="poll" type="button" value="Click me to start polling" />
<br/><br/>
Give me some text here :
<br/>
<input id="data" type="text" />
<br/>
<!-- click this button to release long-polling -->
<input id="release" type="button" value="Click me to release polling" disabled="disabled" />
<br/><br/>
Result after releasing polling :
<div id="result"></div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
// Script to launch polling
$('#poll').click(function() {
$('#poll').attr('disabled', 'disabled');
$('#release').removeAttr('disabled');
$.ajax({
url: 'poll.php',
data: {
poll: 'yes' // sets our $_GET['poll']
},
success: function(data) {
$('#result').html(data);
$('#poll').removeAttr('disabled');
$('#release').attr('disabled', 'disabled');
}
});
});
// Script to release polling
$('#release').click(function() {
$.ajax({
url: 'poll.php',
data: {
release: 'yes', // sets our $_GET['release']
data: $('#data').val() // sets our $_GET['data']
}
});
});
</script>
You can try it here