2015-03-14 5 views
10

Sto lavorando su un progetto in cui ho avuto 2 XMLHttpRequest() oggetti, dicono A e B.Come lavorare con 2 XMLHttpRequest uno dipendente da un altro?

Quello che voglio realizzare è quando Una finitura recupero un elenco di elementi di dati, B verrà attivato per andare a prendere un po ' più elementi basati sui dati precedenti recuperati da A.

Attualmente il mio problema è che i due oggetti funzionano indipendentemente l'uno dall'altro.

Il mio codice è qui sotto:

  var A = new XMLHttpRequest(); 

      var B = new XMLHttpRequest(); 

      A.open("GET", directory, true); 
      A.onreadystatechange = function() { 

       if (A.readyState === 4) { 
        if (A.status === 200 || A.status == 0) { 
        //does... something 
        } 
       } 

      } 
      A.send(null); 
      while(true){ 

       B.open("GET", another_directory, false); 
       B.overrideMimeType("application/document"); 
       B.send(null); 
       if (B.status == "404") 
       continue; 

       //does... something else 
      } 

Questo codice non funziona perché trovo evertime B procedere prima di A può completare. Fondamentalmente non so quale evento usare.

Come posso raggiungere il mio obiettivo? Quali eventi posso utilizzare per poter sincronizzare l'elaborazione B subito dopo aver terminato con A?

+2

Javascript è asincrono. Hai bisogno di conoscere i callback ... fai una funzione, al termine della richiamata alla funzione B ... – zipzit

+0

a seconda del browser che stai usando e se ciò su cui stai lavorando non sarà pronto per l'uso molto presto, e specialmente se questo è per te suggerirei di imparare a usare 'fetch': http://updates.html5rocks.com/2015/03/introduction-to-fetch –

risposta

3

(Dopo una lunga modifica) Consiglio vivamente di dedicare del tempo a comprendere la natura delle chiamate asincrone all'interno di JavaScript. Ecco un po 'di lettura consigliata. Asynchronous Programming in JavaScript Penso che sia abbastanza semplice da capire cosa sta succedendo. Nota: interrompere la lettura su "Enter Mobl".

In JavaScript quando si chiama una funzione, il sistema pone tale funzione in una "coda" con un'istruzione implicita per procedere ed eseguirla il prima possibile. Lo fa per ogni chiamata di funzione. Nel tuo caso stai dicendo al sistema di eseguire A, quindi esegui B. A entra in coda, B entra in coda. Sono presentati come singole funzioni. B capita di correre prima.

Per le funzioni normali, se si desidera controllare la sequenza, è possibile nidificare la chiamata di funzione A all'interno della chiamata di funzione B. Ma oops. Stai utilizzando XMLHttpRequest, in modo da limitare la tua capacità di personalizzare le funzioni. Continuare a leggere. Controlla Ajax Patterns on the subject Guarda il paragrafo per "Chiamate asincrone". Guardate il vostro codice di ...

A.onreadystatechange = function() { 
    if (A.readyState === 4) { 
     if (A.status === 200 || A.status == 0) { 
      //does... something 
      (RUN ALL THE B.methods right here...) 
     } 
    } 
} 

Penso che vi porterà a destinazione, supponendo che si desidera una soluzione jQuery.

Per la persona che vuole solo un sistema funzionante e non vuole capire meglio la lingua, ecco una soluzione jquery ... Nota come la chiamata della funzione B è annidata all'interno della chiamata della funzione A. Si noti che l'ordine di questo annidamento si basa sulla presenza del tag di successo jQuery. Se non si utilizza jQuery, sarà necessario nidificare manualmente le funzioni in modo appropriato.

var special_value; 
$("button").click(function(){ 
    $.ajax({url: "demo_testA.html", 
      type: 'GET', 
      success: function(resultA){ 
       special_value = resultA; 
       $.ajax({url: "demo_testB.html", 
         type: 'GET', 
         data: special_value, 
         success: function(resultB){ 
          $("#div1").html(resultB); 
       }}); 
    }); 
}); 

Dirò, sarebbe molto più semplice aiutarvi ad aiutarvi con l'uso di comunicazioni migliori. Se non ti piace qualcosa, allora così afferma. Se non capisci qualcosa, chiedi maggiori chiarimenti o modifica la tua affermazione sul problema. Il feedback è una buona cosa.

+4

La domanda non è stata taggata jQuery, e questa risposta non riesce a dare alcuna spiegazione di i problemi o la soluzione suggerita. – Bergi

+0

Accidenti, ho pensato che fosse ovvio che il problema riguardava il 98% delle chiamate alle funzioni javascript e il 2% di XMLHttpRequest(). Leggi il mio commento sotto la domanda originale. Non era chiaro che ikis intendesse una soluzione senza jQuery. Controlla i suoi commenti di ritorno alla mia soluzione .. ooops. Non ha mai fornito alcun feedback alla risposta che ho fatto tre settimane fa. Invece, ha aggiunto una taglia (che non mi ha mai propagandato un messaggio? Ehm ... perché no?) Sulle etichette ... hai mai visto domande con scelte di tag scadenti? (sempre.) Avrebbe potuto facilmente menzionare no-jquery rqmt nella sua domanda. – zipzit

+1

Sicuro. Ma la tua risposta non fornisce alcuna comprensione delle chiamate di funzione (asincrone), solo uno snippet di esempio jQuery. Una risposta valida non ha bisogno di includere XHR e può contenere jQuery; ma non deve fare affidamento su jQuery. – Bergi

11

Ok, quindi iniziamo con il codice. Ho aggiunto alcuni commenti ad esso, così ora si può capire l'origine del problema:

var A = new XMLHttpRequest(); //You create an XMLHttpRequest object 
var B = new XMLHttpRequest(); //And an another 

A.open("GET", directory, true); 

/* Now you open a GET request to DIRECTORY, with async TRUE. The third parameter can 
make a request sync or async, but sync is not recommended as described below. */ 

A.onreadystatechange = function() { 
    if (A.readyState === 4) { 
     if (A.status === 200 || A.status == 0) { 

     /* So you registered an event listener. It runs when the readyState changes. 
     You can use it to detect if the request is finished or not. If the readyState is 
     4, then the request is finished, if the status code is 200, then the response is 
     OK. Here you can do everythin you want after the request. */ 

     } 
    } 

} 

A.send(null); //Now you send the request. When it finishes, the event handler will 
// do the processing, but the execution won't stop here, it immediately goes to the 
// next function 

while(true){ // Infinite loop 
    B.open("GET", another_directory, false); //Open request B to ANOTHER_DIRECTORY, 
    // but now, request B will be synchronous 

    B.overrideMimeType("application/document"); // Configure mime type 

    B.send(null); // Send the request 

    if (B.status == "404") 
     continue; 
     // If it's not found, then go to the next iteration 

    // and do something else 
} 

Spero che ora si può vedere l'origine del problema. Quando si esegue questo script, quindi si avvia una richiesta asincrona e quindi si avvia immediatamente il successivo. Ora puoi scegliere tra 2 modi.

Run successiva richiesta da richiamata (consigliato)

E 'il modo migliore. Quindi inizia la tua prima richiesta (asincrona) e nel listener dell'evento (dove esegui l'elaborazione) puoi avviare la richiesta successiva. Ho fatto un esempio commentato qui: http://jsfiddle.net/5pt6j1mo/1/

(lo si può fare senza di matrici - era solo un esempio)

Se si utilizza in questo modo, allora l'interfaccia grafica non si blocca fino a quando si è in attesa per risposta. Tutto sarà responsabile in modo da poter interagire con la pagina, è possibile creare pulsante di annullamento, ecc

sincrono AJAX (non raccomandato)

io non lo consiglio perché "XMLHttpRequest sincrono sul thread principale è deprecato "in Chrome, ma se vuoi davvero, puoi provare a utilizzare questa soluzione. Così la funzione aperta di un XMLHttpRequest ha 3 argomenti:

  • METODO: quali HTTP methid da usare
  • URL: l'URL per richiedere
  • ASYNC: richiesta asincrona? Se false, sarà sincrono, il che significa che dopo aver chiamato .send(), sospenderà l'esecuzione fino a quando la risposta non ritorna.

Quindi, se si imposta il terzo parametro su FALSE, è possibile farlo facilmente ... ma non si dovrebbe!

10

Ecco una soluzione alternativa, utilizzare the fetch API o promisify native XHR e questo problema diventa molto più semplice:

fetch(directory).then(function(response){ 
    // some processing 
    return fetch(another_directory); // can change content type too, see the mdn docs 
}).then(function(responseTwo){ 
     // all processing is done 
}).catch(function(err){ 
     // handle errors from all the steps above at once 
}); 

Questo è altrettanto nativo XHR, ed è molto più semplice da gestire con promesse.

+0

Wow. Molto conveniente. Non è del tutto sicuro che il recupero sia pronto per la prima serata (la tabella di compatibilità dice che non è supportato su Safari?) Ma molto interessante. – zipzit

+0

Può essere facilmente riempito di poligoni nei browser che non lo supportano ancora –

Problemi correlati