Reputation: 42140
I'm trying to implement a comet style, long polling connection using an XMLHttpResponse object. The idea is to maintain an open connection to a server which sends data when it is available (faking push). As soon as the XHR object completes, I need to spawn a new one to wait for any fresh data.
Below is a snippet of code which outlines a solution that works but, as the comment says, only because of a timeout which I need to get rid of.
window.onload = function(){
XHR.init();
}
XHR = {
init: function() {
this.xhr = new XMLHttpRequest();
this.xhr.open( "GET", "proxy.php?salt="+Math.round( Math.random()*10000 ), true );
this.xhr.onreadystatechange = this.process.bind( this );
this.xhr.send( null );
},
process: function() {
if( this.xhr.readyState == 4 ) {
// firebug console
console.log( this.xhr.responseText );
// ** Attempting to create new XMLHttpRequest object to
// replace the one that's just completed
// doesn't work without the timeout
setTimeout( function() { this.init() }.bind( this ), 1000 );
}
}
}
Function.prototype.bind = function( obj ) {
var method = this;
return function() {
return method.apply( obj, arguments );
}
}
// proxy.php - a dummy that keeps the XHR object waiting for a response
<?php
$rand = mt_rand( 1, 10 );
sleep( $rand );
echo date( 'H:i:s' ).' - '.$rand;
I think the problem might be that you can't delete an object (xhr) from it's own event handler (process) as is the case here. especially because the 'this' within the handler is bound to an object (XHR) which contains the object (xhr) I'm trying to delete. Kinda circular!
Can anyone help? The above example is the closest I can get.
Upvotes: 2
Views: 6286
Reputation: 31
Just add xhr = null
inside the init
function.
The xhr
will be assigned a new connection, and thus will not take previous HTTPRequest
value.
init: function() {
xhr = null;
this.xhr = new XMLHttpRequest();
this.xhr.open( "GET", "proxy.php?salt="+Math.round( Math.random()*10000 ), true );
this.xhr.onreadystatechange = this.process.bind( this );
this.xhr.send( null );
},
Upvotes: 0
Reputation: 49582
You probably shouldn't use XMLHTTPRequest at all for this.
Several years ago, long before XMLHTTPRequest was known, I created a chat program to be used in a normal browser. The window with the chat was in a frame where the data come from a cgi-script that never ended. Whenever there was new data, I just sent it and it was immediately displayed at the client.
I guess you can use something similar today:
The data could be encapsulated in SCRIPT-tags. If I remember correctly browsers require to have the whole content of the script tag before trying to evaluate it. Call your update function:
<script type="text/javascript">myupdate("mydata");</script>
Upvotes: 0
Reputation: 123443
You might have an easier time implementing reuse, adding in the abort()
method:
XHR = {
init: function() {
if (!this.xhr) { // setup only once
this.xhr = new XMLHttpRequest();
this.xhr.onreadystatechange = this.process.bind( this );
}
this.xhr.abort(); // reset xhr
this.xhr.open(/*...*/);
this.xhr.send(null);
},
process: function() {
if( this.xhr.readyState == 4 ) {
// firebug console
console.log( this.xhr.responseText );
// start next round
this.init();
}
}
};
@meouw [comment]
If you're getting the same result, than I'd guess you're have a cache issue (that Math.random()
isn't solving) or you're not marking what's been sent over previous requests (resending the same data each time).
Upvotes: 0
Reputation: 90980
Just use jquery and do something like this:
function getData() {
$.getJSON(someUrl, gotData);
}
// Whenever a query stops, start a new one.
$(document).ajaxStop(getData, 0);
// Start the first query.
getData();
My slosh examples do this (since it's pretty much a comet server).
Upvotes: 1
Reputation: 42140
@stu
In this app response time is key - actually what's important is that all clients are updated simultaneously (or as close as possible)
the number off connections will be fairly limited ~50max and the interval between changes could be several minutes.
If polling is used it would need to be very short ~100ms which would lead to an awful lot of unnecessary requests (which will be expensive for the little php socket server I've cobbled together - I know, I know python would be better for the server but I don't know it well enough )
Upvotes: 0
Reputation: 8805
But to actually try and answer your question, the way to delete things that aren't this is to set a timer to call a function that does the deleting, that way, it is not itself that is being deleted.
Upvotes: 0
Reputation: 8805
What you're doing is effectively polling, why make it more complex than it needs to be, and just poll every few seconds? Or every second, how much time are you really saving and is it really that important, and you're going to be tying up an awful lot of sockets on the server end if you have a lot of users.
Upvotes: 0