2009-07-10 16 views
14

Pagina Web richiesta client dal server. Clent richiede quindi che vengano eseguiti ulteriori calcoli; server esegue serie di calcoli e invia risultati parziali non appena sono disponibili (formato di testo, ogni riga contiene elementi separati separati). Client aggiorna la pagina web (con JavaScript e DOM) utilizzando le informazioni fornite dal server.Implementazione cross-browser di "HTTP Streaming" (push) Pattern AJAX

Questo sembra adattarsi al modello HTTP Streaming (current) dal sito Ajaxpatterns.

La domanda è come farlo in modalità cross-browser (browser agnostico), preferibilmente senza utilizzare framework JavaScript, o utilizzando un framework leggero come jQuery.

Il problema inizia con la generazione di XMLHttpRequest in modalità cross-browser, ma penso che l'elemento principale sia che non tutti i browser implementano correttamente onreadystatechange da XMLHttpRequest; non tutti i browser chiamano l'evento onreadystatechange su ogni server flush (come forzare lo svuotamento del server dallo script CGI (in Perl)?). Il codice di esempio su Ajaxpatterns si occupa di ciò usando il timer; dovrei rilasciare la soluzione timer se rilevo risposta parziale da onreadystatechange?


Aggiunto 11-08-2009

soluzione attuale:
Io uso la seguente funzione per creare l'oggetto 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; 
} 

Se dovessi usare alcuni (preferibilmente leggero) framework JavaScript come jQuery, mi piacerebbe avere fallback se utente sceglie di non installare jQuery.

Io uso il seguente codice per avviare AJAX; setInterval viene utilizzato perché alcuni browser chiamano onreadystatechange solo dopo che il server chiude la connessione (che può richiedere fino a decine di secondi), e non appena il server scarica i dati (circa ogni secondo o più spesso).

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

     pollTimer = setInterval(handleResponse, 1000); 
} 

La funzione handleResponse è quello più complicato, ma il disegno di esso appare come il seguente. Può essere fatto meglio? Come si farebbe usando un leggero framework JavaScript (come 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

È necessario aggiungere l'esempio di codice come risposta e contrassegnarlo come corretto! –

+4

"se l'utente decide di non installare jQuery"? – Basic

+0

Ciao, ho appena trovato la soluzione, ma temo che non funzionerà ancora con IE, dal momento che quando cercherete di ottenere il responseText mentre le richieste non sono ancora terminate, otterrete il seguente messaggio: "I dati necessari per completare questa operazione non sono ancora disponibili". –

risposta

2

La soluzione a cui si è collegato non è affatto AJAX, in realtà. Lo chiamano HTTP Streaming ma in sostanza è solo un lungo polling.

Nell'esempio a cui si collegano, è possibile vedere di persona abbastanza facilmente con firebug. Attiva il pannello Rete - non ci sono voci XHR, ma per caricare la pagina originale bastano solo 10 secondi per acconciare. Questo perché usano PHP dietro le quinte per ritardare l'output dell'HTML. Questa è l'essenza del polling lungo: la connessione HTTP rimane aperta e l'HTML periodico inviato indietro è comandi javascript.

Si può scegliere di fare il polling completamente sul lato client, però, con setTimeout() o setInterval()

Un esempio 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

Non esattamente quello che voglio. Il calcolo sul server genera l'output in formato di testo normale. Con XHR posso ottenere questa risposta direttamente nel client (onreadystatechange on flush/timer) e modificare la pagina web in base ai dati parziali che ottengo. –

+0

Cosa non è quello che vuoi? Il lungo sondaggio? Non sto raccomandando alcun metodo - ti sto solo dicendo quali sono le tue opzioni. –

+0

Nel caso in cui si voglia utilizzare il pooling lungo (Comet), si dovrebbe prendere in considerazione l'utilizzo del software del server Meteor, poiché Apache non è progettato per questo genere di cose. E c'è anche una libreria javascript che gestisce quasi tutto per te, non riesco a ricordare il suo nome, lo pubblicherà in seguito. – usoban

0

Vorrei dare un'occhiata al orbita

Utilizzano diverse implementazioni di trasporto su cometa che scelgono in base alla configurazione e allo sniffing del browser.

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

e cercare "Orbited.CometTransports"

Alcuni dei diversi tipi di trasporto deve corrispondere l'attuazione backend, in modo da avere uno sguardo al lato server per orbita anche.