Long jQuery poll (from the PHP server side)

I have a little nightmare here, so any help would be greatly appreciated! First, I will explain what I am trying to do:

I am trying to implement the system described here: https://stackoverflow.com/a/166268/2126 on my localhost MAMP server using the Yii framework. I have a function that checks if there are any new notifications in the database - if so, then they analyze them, and json encodes them. I have this function called in a while loop every 5 seconds.

So: going to / user / unreadNotifications starts the following

Yii::log('test'); // to check it getting called $this->layout=false; header('Content-Type: application/json'); // LONG POLLING while (Yii::app()->user->getNotifications() == null) { sleep(5); } echo Yii::app()->user->getNotifications(); // prints out json if new notification Yii::app()->end(); return; 

This works fine - went to the link in the browser and confirmed the json answer - all is well.

Then I tried all kinds of jQuery things to make it work ... ONLY, as I found, works with $.ajax with a POST type, but ONLY when there is a notification about the wait (so some json returns), $.get or $.post gets "interrupted" (displayed in firebug), but the url is called (because I see that the log file is updated) - odd.

My initial setup with $.get :

  <script type="text/javascript"> function notificationPoll() { $.get('<?php echo Yii::app()->createUrl('user/unreadNotifications') ?>','', function(result) { $.each(result.events, function(events) { alert('New Notification!'); }); notificationPoll(); }, 'json'); } </script> <script type="text/javascript"> $(document).ready(function() { $.ajaxSetup({ timeout: 60 //set a global ajax timeout of a minute }); notificationPoll(); }); </script> 

For some reason, it's just "interrupted." I tried using "jsonp", although this is not a CORS request .. but this does not work either.

It seems it’s not going anywhere! Can anyone chip?

Many thanks

+8
json jquery ajax php getjson
source share
4 answers

How about this one. I guess $. (Get) is in a function called notificationPoll (); which is reprinted upon completion.

 $.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 used done and always here, as jQuery says, discounts success: fail:

+3
source share

You must be sure that the function completes within a reasonable time. What you can do is:

 $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 configure the polling function as a timer using setInterval (). Now the function will be called every, say, 10 seconds, and you may need to configure the semaphore to avoid calling it before returning to the previous iteration:

 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 should check (in the .done() ) that there is a notification:

 function(data) { if (data.hasOwnProperty('nothing')) { alert('No notifications'); return; } console.log(data); ... } 

Now one important thing is what your notice looks like . Here I assumed that this is a JSON encoded string . But if it is an array or object returned by the Yii function, you need to handle its encoding. It can be even cleaner without IF:

 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. )); 

Decoding is already being processed by jQuery, so the above data variable will already be a Javascript object, and you don't need to call JSON.parse . You can verify that data is an object, and that it has the expected properties. This will warn you of any errors.

To handle navigation on another page, you can save the timer identifier of the setInterval() user with the Javascript function request in a global variable and delete the timer when the page calls onUnload() to disable polling.

+3
source share

What returns getNotifications if there are no notifications? jQuery expects the JSON format to be returned, but when you just repeat the empty string, the request fails because the response format is not JSON. Be sure to repeat the JSON string every time.

+2
source share

I'm interested in code interruption, and maybe your answer. This can happen for several reasons.

  • Query.get error. Ajax call does not work for any reason. Analysis error.
  • Syntax Bad javascript. For example: the success handler code expects the event property in the input argument to be incorrect.

For jQuery.get, as suggested in the jQuery.get documentation ( https://api.jquery.com/jQuery.get/ ), the function may work silently, I suggest using .ajaxError to find out if fetching is working.

If a query with jQuery.get () returns an error code, it will fail, unless the script also calls the global .ajaxError () method. Alternatively, as in jQuery 1.5, the .error () method of the jqXHR object returned by jQuery.get () is also available for error handling.

For javascript syntax error, I suggest going through the Firebug debugger. Add a breakpoint to the first line in the success handler, and then release each line. This is tiring, but it works.

+1
source share

All Articles