2013-09-01 2 views
6

Привет, я понимаю, что при длительном опросе вы продолжаете поддерживать связь с сервером надолго, пока не получите ответ от сервера, а затем снова выполните опрос и дождитесь следующего ответа. Однако я, похоже, не понимаю, как его кодировать. Существует этот код, ниже которого используется длинный опрос, но я не кажется, чтобы получить егоКак работает длительный опрос javascript?

(function poll(){ 
$.ajax({ url: "server", success: function(data){ 
    //update page based on data 

}, dataType: "json", complete: poll, timeout: 30000 }); 
})(); 

Но как соединение остается открытым здесь. Я понимаю, что функция «опрос» запускается снова после получения ответа от сервера. Но как открыть соединение?

Edit1: - Было бы здорово, если бы кто-то может объяснить, что бы тайм-аут на самом деле здесь

+0

Возможно, соединение не поддерживается открытым. – rene

+0

как вы препятствуете серверу закрыть соединение. Если запрос будет отправлен на сервер, он ответит, и тогда соединение будет автоматически закрыто. – Rasmus

+0

@itamecodes: вы пишете свой сервер, чтобы он не отвечал, пока он не получит данные для ответа. – Eric

ответ

7

Клиент не может заставить сервер поддерживать соединение открытым. Сервер просто не закрывает соединение. Сервер должен будет сказать в какой-то момент «вот и все, здесь больше нет контента, пока». При длительном опросе сервер просто никогда не делает этого и заставляет клиента ждать больше данных, которые он постепенно истощается по мере поступления обновлений. Это длинный опрос.

На стороне клиента можно периодически проверять данные, которые уже были получены, а запрос еще не завершен. Таким образом, данные могут иногда отправляться с сервера по тому же открытому соединению. В вашем случае это не делается, обратный вызов success будет срабатывать только после завершения запроса. Это в основном дешевая форма длительного опроса, в которой сервер заставляет клиента ждать события, отправляет данные об этом событии и затем закрывает соединение. Клиент принимает это как триггер, обрабатывает данные, а затем повторно подключается к серверу, чтобы дождаться следующего события.

+0

Я предполагаю, что получаю это сейчас. Не могли бы вы поделиться каким-то скелетом код сервера для большей ясности – Rasmus

+0

@itamecodes Важная вещь: для серверной части вам необходимо установить конфигурацию, чтобы не закрывать соединение по таймауту. – VisioN

+1

@itame Простым образцом будет 'while (! ($ Data = checkDatabaseForData())) sleep (1); echo $ data; '- Это зависит от того, на каком языке вы работаете на стороне сервера, такая система, как node.js, будет намного более элегантной, чем цикл' sleep'. – deceze

1

Соединение не остается открытым все время. Он автоматически закрывается, когда ответ получен от сервера, и сервер закрывает соединение. При длительном опросе сервер не должен немедленно отправлять обратно данные. В ajax complete (когда сервер закрывает соединение), новый запрос отправляется на сервер, который снова открывает новое соединение и начинает оставаться в ожидании для нового ответа.

Как уже упоминалось, длительный процесс опроса обрабатывается не только на стороне клиента, но главным образом на стороне сервера. И не только по серверному скрипту (в случае PHP), но и по самому серверу, который не закрывает «повешенным» соединением таймаутом.

FWIW, WebSockets использовать постоянно открытое соединение с серверной стороной, что позволяет получать и отправлять данные без закрытия соединения.

+0

Тогда как этот код отличается от традиционного опроса. Кстати, я не отказался от этого ответа – Rasmus

+1

@itamecodes Это * * традиционный подход «длинного опроса». – VisioN

+0

@Rasmus традиционный опрос = AJAX Опрос: запрошенная веб-страница выполняет javascript, который запрашивает файл с сервера с * регулярными * интервалами (например, 0,5 секунды). см. -http: //stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet –

6

Я думаю, что это затрудняет понимание того, что обсуждение сосредоточено на программировании на стороне клиента.

Длительный опрос - это не только шаблон на стороне клиента, но требует, чтобы веб-сервер поддерживал соединение открытым.

Предпосылки: Клиент хочет получать уведомления от веб-сервера, когда что-то происходит или доступно, например, сообщите мне, когда приходит новое письмо без меня, чтобы вернуться и спросить каждые несколько секунд.

  1. Клиент открывает подключение к определенному URL-адресу на веб-сервере.
  2. Сервер принимает соединение, открывает управление сокетами и диспетчерами, независимо от того, какой серверный код обрабатывает это соединение (скажем, сервлет или jsp в java или маршрут в RoR или node/express).
  3. Код сервера ждет, пока не появится событие или информация. Например, когда приходит электронное письмо, он видит, есть ли какое-либо из «ожидающих соединений» для конкретного почтового ящика. Если они есть, ответьте соответствующими данными.
  4. Клиент получает данные, делает свою вещь, а затем запускает другой запрос на опрос.
2

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

Javascript просто делает регулярный запрос, но сервер не должен немедленно отвечать на запрос. Если сервер не имеет ничего достойного возврата (т. Е. Изменение, ожидаемое браузером, еще не произошло), сервер просто ждет, что держит соединение открытым.

Если в течение некоторого времени на сервере ничего не происходит, клиентская сторона отключится и сделает новый запрос, или сервер может выбрать пустой результат, чтобы сохранить поток.

2

Я искал, чтобы сделать что-то с шахматными данными, где некоторые вернутся сразу, но последние несколько результатов могут вернуться через 10-15 секунд. Я создал быстрый немного JQuery хак, но это своего рода делать то, что я хочу (до сих пор не уверен, если это имеет смысл использовать его Тхо):

(function($) { 
    if (typeof $ !== 'function') return; 
    $.longPull = function(args) { 
     var opts = $.extend({ method:'GET', onupdate:null, onerror:null, delimiter:'\n', timeout:0}, args || {}); 
     opts.index = 0; 
     var req = $.ajaxSettings.xhr(); 
     req.open(opts.method, opts.url, true); 
     req.timeout = opts.timeout; 
     req.onabort = opts.onabort || null; 
     req.onerror = opts.onerror || null; 
     req.onloadstart = opts.onloadstart || null; 
     req.onloadend = opts.onloadend || null; 
     req.ontimeout = opts.ontimeout || null; 
     req.onprogress = function(e) { 
      try { 
       var a = new String(e.srcElement.response).split(opts.delimiter); 
       for(var i=opts.index; i<a.length; i++) { 
        try { 
         var data = JSON.parse(a[i]); // may not be complete 
         if (typeof opts.onupdate==='function') opts.onupdate(data, i); 
         opts.index = i + 1; 
        } catch(fx){} 
       } 
      } 
      catch(e){} 
     }; 
     req.send(opts.data || null); 
    }; 
})(jQuery); 

Во многом непроверенной, но это, казалось, делать то, что вы имели в виду. Я могу думать о всевозможных способов он может пойти не так, хотя ;-)

$.longPull({ url: 'http://localhost:61873/Test', onupdate: function(data) { console.log(data); }}); 
2

В соответствии с просьбой, вот некоторые псевдо NodeJS код:

function respond_to_client(res,session,cnt) 
{ 
    //context: res is the object we use to respond to the client 
    //session: just some info about the client, irrelevant here 
    //cnt: initially 0 

    //nothing to tell the client, let's long poll. 
    if (nothing_to_send(res,session)) 
    { 
     if (cnt<MAX_LONG_POLL_TIME) 
     { 
      //call this function in 100 ms, increase the counter 
      setTimeout(function(){respond_to_client(request_id,res,session,cnt+1)},100); 
     } 
     else 
     { 
      close_connection(res); 
      //Counter too high. 
      //we have nothing to send and we kept the connection for too long, 
      //close it. The client will open another. 
     } 
    } 
    else 
    { 
     send_what_we_have(res); 
     close_connection(res); 
     //the client will consume the data we sent, 
     //then quickly send another request. 
    } 

    return; 

} 
1

Я думаю, никто должным образом не объясняет, почему мы необходимо тайм-аут в коде. Из jQuery Ajax docs:

Установите тайм-аут (в миллисекундах) для запроса. Это переопределит любой глобальный тайм-аут с $ .ajaxSetup(). Период ожидания начинается с момента вызова $ .ajax; если в настоящее время выполняется несколько других запросов, и у браузера нет доступных соединений, можно запросить тайм-аут до его отправки

Опция тайм-аута действительно не задерживает следующее выполнение в течение X секунд. он устанавливает максимальный тайм-аут для текущего вызова. Хорошая статья о тайм-аутах - https://mashupweb.wordpress.com/2013/06/26/you-should-always-add-timeout-to-you-ajax-call-in-jquery/

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