jQuery Long Polling (With PHP server side)
You must be sure that the function terminates inside a reasonable time. What you could do is this:
$ttl = 10;while ($ttl--) { $json = Yii::app()->user->getNotifications(); if (null != $json) { break; } sleep(1);}if (null == $json) { $json = json_encode(array( 'nothing' => true ));}header('Content-Type: application/json');echo $json;Yii::app()->end();return;
You set up the polling function as a timer using setInterval(). The function will now be called every, say, 10 seconds, and you may need to set up a semaphore to avoid it being called before the previous iteration has returned:
var timer = setInterval( function() { if (this.calling) { return; } var fn = this; fn.calling = true; $.post(url) .done(function(data) { .. }) .always(function() { fn.calling = false; }); }, 10000);
Then the polling function in AJAX needs to check (in the .done()
) callback) that the notification is there:
function(data) { if (data.hasOwnProperty('nothing')) { alert('No notifications'); return; } console.log(data); ...}
Now one important thing is what does your notification look like. Here I've assumed it is a JSON encoded string. But if it is an array or object that the Yii function returns instead, you need to handle its encoding. This might be even cleaner, without any IF's:
header('Content-Type: ...die(json_encode( array( 'status' => 'success', 'notification' => $json /* This is NULL or an array */ ) // Javascript side we check that data.notification is not null.));
The decoding is already handled by jQuery, so the variable "data" above will already be a Javascript object, and you need not call JSON.parse
. You can check that data
is an object though, and that it has the expected properties. That will warn you of any errors.
To handle the navigation to another page, you can store the setInterval()
-supplied timer ID of the polling Javascript function in a global variable, and delete the timer when the page calls onUnload()
to deactivate the polling.
How about this. I assume the $.(get) is in a function called notificationPoll(); which is re-called once completed.
$.ajax({ url: event_feed_href, async: false, timeout: 60000, done: function(data) { var got_json=false; try { var json = JSON.parse(data); got_json=true; } catch(e) { // failed to return JSON data alert('Wierd!'); } if(got_json) { // process json data alert('New Notification!'); } }, always: function() { notificationPoll(); } });
I've used done and always here as jQuery says is depreciating success: fail: