2012-07-02 2 views
8

У меня здесь немного кошмар, поэтому любая помощь будет с благодарностью оценена! Во-первых, я объясню, что я пытаюсь сделать:jQuery Длительный опрос (со стороны сервера PHP)

Я пытаюсь реализовать систему, описанную здесь: https://stackoverflow.com/a/1086448/1034392 на моем сервере MAMP-сервера localhost с использованием инфраструктуры Yii. У меня есть функция, которая проверяет, есть ли какие-либо новые уведомления в БД - если да, то они анализируют их, а json кодирует их. У меня есть функция, называемая циклом while каждые 5 секунд.

Итак: Собираюсь/пользователь/unreadNotifications запускает следующую

Yii::log('test'); // to check it's 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; 

Это работает отлично - пошел по ссылке в браузере и проверить реакцию JSon - все хорошо.

Я попытался использовать все виды материалов jQuery, чтобы заставить их работать ... ТОЛЬКО способ, которым я нашел работу, - использовать $.ajax с типом POST, но ТОЛЬКО, когда есть уведомление о ожидании (так что некоторые json возвращаются). $.get или $.post получает «aborted» (отображается в firebug), но URL-адрес вызывается (потому что я вижу, что файл журнала обновляется) - нечетно.

Моя первоначальная настройка с помощью $.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> 

Это просто получает "прервана" по какой-то причине. Я пробовал использовать «jsonp», хотя это не запрос CORS .. но это тоже не работает.

Кажется, никуда не денется! Может ли кто-нибудь чип?

Большое спасибо

+0

Забыл упомянуть: когда я использую $ .ajax с типом POST и нет никаких уведомлений для отображения, любая страница сайта, на которой код jQuery просто не загружается, пока не появится уведомление. –

+0

Ошибка журнала консоли ?? вставьте его .. –

ответ

2

, что делает getNotifications вернуться, если нет уведомлений? jQuery ожидает, что формат JSON будет возвращен, но когда вы просто повторяете пустую строку, запрос терпит неудачу, так как формат ответа не является JSON. Обязательно повторяйте строку JSON каждый раз.

+0

спасибо Энди. В настоящее время getNotifications() возвращает null, если нет уведомлений, поэтому user/unreadNotifications просто петли и на самом деле ничего не возвращает, пока не появится новое уведомление. –

+0

он должен просто переждать, без ответа. Возможно, лучшая структура $ .ajax будет легче отлаживать, с личным таймаутом, успехом, попробовать {parse json, data_available} catch (e) {}, data_available: обрабатывать данные JSON, сбой – Waygood

+0

Ок - похоже, я сузил его вниз, наконец! Когда я вызываю $ .ajaxSteup() и устанавливаю таймаут .. он устанавливает тайм-аут в миллисекундах? Я увеличил это до 60000 (60 секунд), и теперь $ .get не «прерывает»! Одна из последних проблем, хотя - загрузка страницы изначально хорошо, однако переход на другую страницу просто застревает. Есть ли способ закрыть обработку GET-запроса при выходе из страницы? (Я предполагаю, что это приводит к тому, что следующая страница не загружается.) –

3

Как насчет этого. Я предполагаю, что $. (Get) находится в функции, называемой notificationPoll(); который переиздается после завершения.

$.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(); 
     } 
    }); 

Я использовал сделать и всегда здесь, как JQuery говорит обесценивается успех: провал:

+0

Длительный опрос должен быть без тайм-аута клиента. Тайм-аут может использоваться только для сетевых ошибок и повторного подключения. – Deep

3

Вы должны быть уверены, что функция заканчивается в разумные сроки. Что вы можете сделать, так это:

$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; 

Вы установили функцию опроса в качестве таймера с помощью setInterval(). Функция теперь будет называться каждый, скажем, 10 секунд, и вы, возможно, потребуется создать семафор, чтобы избежать его называют до предыдущей итерации вернулся:

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

Тогда функция опроса в AJAX необходимо проверить (в .done()) обратного вызова), что уведомление есть:

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

Теперь одна важная вещь , что делает ваше уведомление выглядеть. Здесь я предположил, что это кодированная JSON строка . Но если это массив или объект, возвращаемый функцией Yii, вам нужно обработать его кодировку.Это может быть даже чище, без каких-либо ИФ:

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

Декодирование уже обрабатывается JQuery, так что «данные» переменная выше уже будет объект Javascript, и вы не нужно называть JSON.parse. Вы можете проверить, что dataявляется объектом, хотя и имеет ожидаемые свойства. Это предупредит вас о любых ошибках.

Чтобы обработать навигацию на другой странице, вы можете сохранить setInterval() -использованный идентификатор таймера функции Javascript для опроса в глобальной переменной и удалить таймер, когда страница вызывает onUnload() для деактивации опроса.

1

Меня интересует код прерывания и может быть ваш ответ. Это может произойти по нескольким причинам.

  • Ошибка запроса. Ajax-вызов не работает по каким-либо причинам. Ошибка анализа.
  • Плохой синтаксис javascript. Например: код в обработчике успеха ожидает, что свойство событий во входном аргументе может быть неверным.

Для jQuery.get, как это было предложено в jQuery.get (https://api.jquery.com/jQuery.get/) документации, функция может молча неудачу, я предлагаю использовать .ajaxError, чтобы увидеть, если прибудут не удается.

Если запрос с jQuery.get() возвращает код ошибки, он будет терпеть неудачу, если скрипт также не вызвал глобальный метод .ajaxError(). В качестве альтернативы, как и в jQuery 1.5, для обработки ошибок также доступен метод .error() объекта jqXHR, возвращаемый jQuery.get().

Для синтаксической ошибки javascript я предлагаю пройти через отладчик Firebug. Добавьте точку останова в первую строку в обработчике успеха, а затем отпустите каждую строку. Это утомительно, но это работает.

Смежные вопросы