2011-01-25 12 views
7

Ciao Sto facendo un sito web di scorrimento orizzontale come: http://vanityclaire.com/coda chiamate AJAX

Tuttavia, piuttosto che avere un file HTML di grandi dimensioni, dopo il carico della homepage, sto ajaxing nei figli di casa, utilizzando jQuery. caricare().

Attualmente io per ogni div e ajax nell'url che si trova nel titolo. Ma AJAX ritorna fuori servizio, e mentre aggiungo altre pagine non mi piace il spanging il server con 30+ richieste http: //.

Come faccio in modo sincrono le chiamate AJAX, ovvero attendere che il primo ritorni prima di una richiesta, o addirittura invii due alla volta.

Sto setacciando e non riesco a capire di cosa ho bisogno.

Questo è il mio HTML:

<div id="mainLayout" class="fullwidth scrollArea"> 
    <div class="scrollItems"> 
     <div id="page-1" class="scrollItem" title="/"> 
     <div>HOME PAGE CONTENT</div> 
     </div> 
     <div id="page-2" class="scrollItem" title="/Page2.html"> 
     <div class="loading"> </div> 
     </div> 
     <div id="page-3" class="scrollItem" title="/Page3.html"> 
     <div class="loading"> </div> 
     </div> 

     <div id="page-4" class="scrollItem" title="/Page4.html"> 
     <div class="loading"> </div> 
     </div> 
     <div id="page-5" class="scrollItem" title="/Page5.html"> 
     <div class="loading"> </div> 
     </div> 
    </div> 
    </div> 

E i miei JS:

function s_loadingInitialPages() { 
    var loadingItems = new Array(); 
    $(".scrollArea .scrollItem").each(function() { 
     if ($(this).attr('title') != '/') { 
      var oDelem = $(this); 
      loadingItems.push(oDelem); 
      //alert('test'); 
     } 
    }); 

    for (i = 0; i < loadingItems.length; i++) { 
     // title attribute is the URL to get 
     var ajaxURL = loadingItems[i].attr("title") + '?ajaxPageContent='; 
     $(loadingItems[i]).load(ajaxURL); 

    } 
} 

C'è un plugin posso solo continuare ad aggiungere funzioni a una coda, e lasciare che gestirlo?

+0

se u invia richieste sincrone, il browser si blocca. Suggerisco le chiamate asincrone annidate. – Sid

risposta

18

Il trucco è utilizzare i callback. Fai una chiamata ajax e sul suo callback di successo fai il prossimo.

Per fare ciò basta aggiungerli tutti a una coda e disporre di un wrapper che li manda uno alla volta.

ne ho scritto uno qualche giorno fa. Ti mostrerò una implementazione in un secondo.

// Buffer class. Has a public append method that expects some kind of Task. 
// Constructor expects a handler which is a method that takes a ajax task 
// and a callback. Buffer expects the handler to deal with the ajax and run 
// the callback when it's finished 
function Buffer(handler) { 
    var queue = []; 

    function run() { 
     var callback = function() { 
      // when the handler says it's finished (i.e. runs the callback) 
      // We check for more tasks in the queue and if there are any we run again 
      if (queue.length > 0) { 
        run(); 
      } 
     } 
     // give the first item in the queue & the callback to the handler 
     handler(queue.shift(), callback); 
    } 

    // push the task to the queue. If the queue was empty before the task was pushed 
    // we run the task. 
    this.append = function(task) { 
     queue.push(task); 
     if (queue.length === 1) { 
      run(); 
     } 
    } 

} 

// small Task containing item & url & optional callback 
function Task(item, url, callback) { 
    this.item = item; 
    this.url = url; 
    this.callback = callback 
} 

// small handler that loads the task.url into the task.item and calls the callback 
// when its finished 
function taskHandler(task, callback) { 
    $(task.item).load(task.url, function() { 
     // call an option callback from the task 
     if (task.callback) task.callback(); 
     // call the buffer callback. 
     callback(); 
    }); 
} 

// create a buffer object with a taskhandler 
var buffer = new Buffer(taskHandler); 

for (i = 0; i < loadingItems.length; i++) { 
    // title attribute is the URL to get 
    var ajaxURL = loadingItems[i].attr("title") + '?ajaxPageContent='; 
    buffer.append(new Task(loadingItems[i], ajaxURL)); 
} 

Ci scusiamo per il muro di codice. Implementa semplicemente il tuo compito e gestore. Il buffer funzionerà finché il gestore chiama il secondo argomento (il callback) quando ha finito di gestire l'attività.

Quindi basta passarlo a un compito ea un gestore. Il gestore esegue l'ajax e chiama il callback dal buffer quando ritorna l'ajax.

Per il tuo esempio specifico se il carico richiesto è lungo, ci vorrà molto tempo per caricare tutti i 30. Il punto di ajax è di fare il server in parallelo.

Una soluzione di gran lunga migliore nel tuo caso è di fare 30 richieste e quindi prendere i risultati e assicurarsi che i risultati delle tue chiamate ajax vengano aggiunti al dominio solo nell'ordine. Ciò implica l'uso di $ .ajax e l'aggiunta di tenere traccia dell'ordine in qualche modo.

In questo modo il server lo farà il più velocemente possibile e sarà possibile eseguirne il server in ordine una volta ottenuto. In alternativa, se le cose che fai sono veloci, metterle in coda in un buffer non ha penalità.

+0

+1 per una grande idea. – rubayeet

+0

+1. Ecco un trattamento più approfondito di questo metodo - http://www.dustindiaz.com/async-method-queues/ –

+1

Cheers Raynos, che sembra buono, e capirlo in modo sorprendente. Ho trovato anche questo http://www.protofunc.com/scripts/jquery/ajaxManager/ - ho avuto qualche altra opzione. –

1

La maggior parte dei browser è in grado di gestire 6 o più richieste Ajax simultanee in un singolo dominio.
http://www.browserscope.org/?category=network&v=top

Se lo script inserisce 30 richieste ajax contemporaneamente, le prime 6 richieste verranno eseguite molto rapidamente. Successivamente, il browser può iniziare ad assegnare periodi di attesa arbitrari fino a 5 secondi. Chrome è un ottimo esempio di questo comportamento.

Richieste 1-6 ritorno in 5 ms.

Richieste 7-12 ritorno in 5,005 ms.

Richieste 11-18 ritorno in 10,005 ms.

Richieste 19-24 ritorno in 15,005 ms.

Richieste 25-30 ritorno in 20,005 ms.

Si consiglia di creare una coda di richiamate funzione per gestire tutte le richieste Ajax dell'applicazione e elaborare non più di 6 di esse alla volta.

var ajaxCownt = (ajaxCownt == null ? 0 : ajaxCownt); // Make limit globally accessible. 
 
var ajaxKue = (ajaxKue == null ? [] : ajaxKue); // Make queue globally accessible. 
 

 
function doMyAjaxRequest() { 
 
console.log("doing ajax request."); 
 
// Implement ajax request, here. 
 
} 
 

 
for (var i = 1;i <= 30;i++) { 
 
ajaxKue.push(function() { doMyAjaxRequest() }); // Add request to queue. 
 
} 
 

 
while (ajaxCownt != null && ajaxCownt < 6 && ajaxKue != null && ajaxKue.length && ajaxKue.length > 0) { 
 
ajaxCownt++; 
 
console.log("incrementing pending ajax requests counter by 1."); 
 
ajaxKue.shift().call(); 
 
}; 
 

 
// Register an event to detect when an ajax request completes. 
 
// Allow for an additional ajax request to be processed. 
 
$(document).ajaxComplete(function() { 
 
    if (ajaxCownt && ajaxCownt > 0) { 
 
     ajaxCownt--; 
 
     console.log("decrementing pending ajax requests counter by 1."); 
 
    } 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Problemi correlati