2009-07-10 10 views
14

Strona internetowa żądania klienta z serwera. Clent prosi o dodatkowe obliczenia; serwer wykonuje serię obliczeń i wysyła wyniki cząstkowe, gdy tylko są dostępne (format tekstowy, każda linia zawiera oddzielny pełny element). Strona internetowa aktualizacji klienta (z JavaScript i DOM) przy użyciu informacji dostarczonych przez serwer.Wbudowana w przeglądarki wersja "HTTP Streaming" (push) AJAX pattern

Wydaje się to pasować do wersji HTTP Streaming (current) z witryny Ajaxpatterns.

Pytanie brzmi: jak to zrobić w sposób umożliwiający przeglądanie w różnych przeglądarkach (z pominięciem przeglądarki), najlepiej bez korzystania z frameworków JavaScript lub przy użyciu jakiegoś lekkiego frameworka, takiego jak jQuery.

Problem zaczyna się od wygenerowania XMLHttpRequest w modzie w różnych przeglądarkach, ale myślę, że głównym elementem jest to, że nie wszystkie przeglądarki implementują poprawnie onreadystatechange z XMLHttpRequest; nie wszystkie przeglądarki wywołują zdarzenie onreadystatechange na każdym spłukiwaniu serwera (BTW, jak wymusić spłukanie serwera z poziomu skryptu CGI (w Perlu)?). Przykładowy kod na Ajaxpatterns radzi sobie z tym za pomocą timera; czy powinienem zrezygnować z rozwiązania czasomierza, jeśli wykryję częściową odpowiedź z onreadystatechange?


Dodany 11-08-2009

Aktualny rozwiązanie:
używam następującą funkcję do stworzenia obiektu XMLHttpRequest:

function createRequestObject() { 
     var ro; 
     if (window.XMLHttpRequest) { 
       ro = new XMLHttpRequest(); 
     } else { 
       ro = new ActiveXObject("Microsoft.XMLHTTP"); 
     } 
     if (!ro) 
       debug("Couldn't start XMLHttpRequest object"); 
     return ro; 
} 

Gdybym miał użyć niektóre (najlepiej lekki) framework JavaScript jak jQuery, chciałbym mieć awarię, jeśli użytkownik nie instaluje jQuery.

Używam następującego kodu, aby uruchomić AJAX; setInterval jest używany, ponieważ niektóre przeglądarki wywołują onreadystatechange tylko po zamknięciu połączenia przez serwer (co może potrwać nawet kilkadziesiąt sekund), a nie tak szybko, jak serwer opróżnia dane (co sekundę lub częściej).

function startProcess(dataUrl) { 
     http = createRequestObject(); 
     http.open('get', dataUrl); 
     http.onreadystatechange = handleResponse; 
     http.send(null); 

     pollTimer = setInterval(handleResponse, 1000); 
} 

Funkcja handleResponse jest najbardziej skomplikowany, ale szkic wygląda na to poniżej. Czy można to zrobić lepiej? Jak to zrobić przy użyciu niewielkiego szkieletu JavaScript (np. JQuery)?

function handleResponse() { 
    if (http.readyState != 4 && http.readyState != 3) 
     return; 
    if (http.readyState == 3 && http.status != 200) 
     return; 
    if (http.readyState == 4 && http.status != 200) { 
     clearInterval(pollTimer); 
     inProgress = false; 
    } 
    // In konqueror http.responseText is sometimes null here... 
    if (http.responseText === null) 
     return; 

    while (prevDataLength != http.responseText.length) { 
     if (http.readyState == 4 && prevDataLength == http.responseText.length) 
      break; 
     prevDataLength = http.responseText.length; 
     var response = http.responseText.substring(nextLine); 
     var lines = response.split('\n'); 
     nextLine = nextLine + response.lastIndexOf('\n') + 1; 
     if (response[response.length-1] != '\n') 
      lines.pop(); 

     for (var i = 0; i < lines.length; i++) { 
      // ... 
     } 
    } 

    if (http.readyState == 4 && prevDataLength == http.responseText.length) 
     clearInterval(pollTimer); 

    inProgress = false; 
} 
+0

Powinieneś zdecydowanie dodać ten przykład kodu jako odpowiedź i oznaczyć go jako poprawny! –

+4

"jeśli użytkownik nie instaluje jQuery"? – Basic

+0

Cześć, właśnie natknąłem się na twoje rozwiązanie, ale obawiam się, że nadal nie będzie działać z IE, ponieważ kiedy spróbujesz uzyskać responseText, gdy żądania wciąż się nie kończą, otrzymasz następujące komunikat: "Dane niezbędne do ukończenia tej operacji nie są jeszcze dostępne". –

Odpowiedz

2

Rozwiązanie, z którym się łączysz, w rzeczywistości nie jest AJAX. Nazywają to HTTP Streaming, ale to w zasadzie tylko długie sondowanie.

W przykładzie, do którego prowadzą odnośniki, można dość łatwo zobaczyć z firebugiem. Włącz panel Net - nie ma wpisów XHR, ale ładowanie oryginalnej strony zajmuje tylko 10 sekund. To dlatego, że używają PHP za kulisami, aby opóźnić wyjście HTML. Jest to esencja długiego odpytywania - połączenie HTTP pozostaje otwarte, a okresowy HTML odesłany jest poleceniem javascript.

Można zdecydować się zrobić odpytywanie całkowicie po stronie klienta, choć z setTimeout() lub setInterval()

przykładem jQuery

<script type="text/javascript"> 
    $(document).ready(function() 
    { 
    var ajaxInterval = setInterval(function() 
    { 
     $.getJSON(
     'some/servie/url.ext' 
     , { sample: "data" } 
     , function(response) 
      { 
      $('#output').append(response.whatever);   
      } 
    ); 
    }, 10000); 
    }); 
</script> 
+0

Nie exaxtly, co chcę. Obliczenia na serwerze generują dane wyjściowe w formacie zwykłego tekstu. Dzięki XHR mogę uzyskać tę odpowiedź bezpośrednio w kliencie (onreadystatechange on flush/timer) i edytować stronę internetową według częściowych danych, które otrzymuję. –

+0

Czego nie chcesz? Długi głosowanie? Nie polecam żadnej z tych metod - po prostu mówię ci, jakie masz opcje. –

+0

Jeśli chcesz używać długiego łączenia (Comet), powinieneś rozważyć użycie oprogramowania serwera Meteor, ponieważ Apache nie jest przeznaczony do tego typu rzeczy. Istnieje również biblioteka javascript, która obsługuje prawie wszystko, po prostu nie pamiętam jej nazwy, opublikuje ją później. – usoban

0

chciałbym przyjrzeć krążył

Używają kilku implementacji transportu komety, które wybierają w oparciu o konfigurację i węszenie przeglądarki.

Zobacz http://orbited.org/svn/orbited/trunk/daemon/orbited/static/Orbited.js

i szukać „Orbited.CometTransports”

Niektóre z różnych transportów muszą być dopasowane realizacji zaplecza, więc przyjrzeć się stronie serwera na orbicie również.

Powiązane problemy