Radzenie sobie z przyrostową odpowiedzią serwera w AJAX (w JavaScript)

Mam aplikację AJAX, która aktualizuje stronę na podstawie odpowiedzi serwera. Polecenie, na którym opiera się odpowiedź serwera AJAX, zajmuje dużo czasu, aby wygenerować pełną odpowiedź, ale wysyła częściowe informacje, gdy tylko zostanie obliczone. Ta częściowa odpowiedź / częściowa informacja jest wysyłana w „serii”, a czas i rozmiar każdej serii jest nieprzewidywalny. Skrypt CGI (w Perlu), który przesyła dane wyjściowe polecenia do przeglądarki internetowej (na żądanie AJAX), ma włączoną autoflush.

Odpowiedź serwera jest oparta na wyjściu polecenia zewnętrznego. Podczas gdy „time cmd> / dev / null” daje średnio około 10,0 sekund, „time cmd | head> / dev / null” daje mniej niż 0,1 sekundy (na przykład dane). Wszystkie dane są wynikiem pojedynczego wywołania tego polecenia zewnętrznego .

Sytuacja wygląda następująco(Następuje diagram ASCII-art):

 client |     | server
---------     ---------

request -\
          \
           \
            \
             \->

             /- response
            /      .
           /       .
          /  /-    .
       <-/  /      . 
           /       .
          /  /-  [end]
       <-/  /
           /
          /
       <-/

Mam kilka pytań dotyczących tego problemu.

Uwaga: strona serwera jest wykonywana jako skrypt CGI w Perlu i wolałbym widzieć (również) rozwiązanie bez użycia biblioteki JavaScript / framework, takiej jak jQuery.

Wyjściem polecenia używanego po stronie serwera aplikacji AJAX jest linia. Każda grupa linii, zaczynając od jednego zdefiniowanego rodzaju linii, a kończąc na innym rodzaju linii, składa się z danych niezależnych i niezmiennych. Czy powinienem po prostu przesyłać strumieniowo odpowiedź z polecenia jako „tekst / zwykły” i wykonywać przetwarzanie w JavaScript po stronie klienta, czy też powinienem wstępnie przetworzyć dane na serwerze i wysłać całe porcje danych jako JSON przy użyciu typu MIME „application / json”?

Może się zdarzyć, że wkrótce po dużej części danych wysłanych przez serwer nastąpi kolejna porcja danych. Jak radzić sobie z sytuacją, kiedyonreadystatechange handler jest wywoływany, gdy poprzednie wywołanie nie skończyło się? Czy powinienem używać zmiennej globalnej jako semafora lub przekazać zmienną stanu jako parametr obsługi (dobrze, użyjxhr.onreadystatechange = function() { handleRequest(xhr, state) })?

Czy powinienem użyć „text / plain” lub „application / json”, a może „multipart / x0mixed-replace”? Uwaga: ta aplikacja powinna działać w (dowolnej) dowolnej przeglądarce.

Jak radzić sobie z przeglądarką internetową (silniki JavaScript), które wywołują onReadyStateChange dopiero po otrzymaniu pełnej odpowiedzi (więc nie widzęxhr.readyState == 3 tj. częściowa odpowiedź więcej niż raz)? Cóż, obok korzystania z niektórych struktur JavaScript.

Jak radzić sobie z niepełnymi odpowiedziami (które w tej sytuacji oznaczają niepełne linie).

Czy powinienem wysłać znacznik końca odpowiedzi lub polegać na liczniku, aby sprawdzić, czy otrzymaliśmy wszystkie dane, czy też mogę po prostu polegać na wykrywaniuxhr.readyState == 4?

Pomocna byłaby nawet częściowa odpowiedź.

questionAnswers(2)

yourAnswerToTheQuestion