2011-01-25 40 views
7

Hola estoy haciendo un sitio web El desplazamiento horizontal como: http://vanityclaire.com/cola de llamadas AJAX

Sin embargo, en lugar de tener un solo archivo HTML grande, después de la carga de la página, estoy ajaxing en los niños de la casa, usando jQuery. carga().

En este momento, for-each div y ajax en la url que se encuentra en el título. Pero el AJAX vuelve a estar fuera de servicio, y cuando agrego más páginas no me apetece spanging el servidor con más de 30 solicitudes http: //.

Cómo sincronizo hacer las llamadas AJAX, es decir, esperar a que el primero regrese antes de que se solicite otro, o incluso enviar dos a la vez.

He estado rastreando, y no puedo entender lo que necesito.

Esta es mi 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> 

Y mis 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); 

    } 
} 

¿Existe un plugin que sólo puede seguir añadiendo funciones a una cola, y dejar que lo manejan?

+0

si u enviar peticiones síncronas, el navegador se congele. Sugiero llamadas asíncronas anidadas. – Sid

Respuesta

18

El truco es usar las devoluciones de llamada. Haces una llamada ajax y en su exitosa devolución de llamada haces la siguiente.

Para hacer esto, simplemente añádalos a todos en una cola y tenga un envoltorio alrededor que los envíe uno a uno.

Escribí uno hace unos días. Te mostraré una implementación en un segundo.

// 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)); 
} 

Disculpas por la pared del código. Simplemente implemente su propia Tarea y Manejador. El búfer funcionará siempre que el controlador llame al segundo argumento (la devolución de llamada) cuando termine de manejar la tarea.

Luego solo pásalo una tarea y un controlador. El controlador hace el ajax y llama a la devolución de llamada desde el búfer cuando vuelve el ajax.

Para su ejemplo específico si la carga tarda mucho tiempo, esto llevará mucho tiempo cargar los 30. El objetivo de ajax es hacer que el servidor haga cosas en paralelo.

Una solución mucho mejor en su caso es hacer 30 solicitudes y luego ver los resultados y asegurarse de que los resultados de sus llamadas ajax solo se agreguen al dominio en orden. Esto implica usar $ .ajax y agregar un seguimiento del orden de alguna manera.

De esta forma, el servidor lo hará lo más rápido posible y podrá ejecutarlo en orden una vez que lo obtenga. Alternativamente, si las cosas que hace son rápidas, entonces ponerlas en cola en un búfer no tiene ninguna penalización.

+0

+1 para una gran idea. – rubayeet

+0

+1. Aquí hay un tratamiento más exhaustivo de este método: http://www.dustindiaz.com/async-method-queues/ –

+1

Cheers Raynos, que se ve bien, y lo entiendo sorprendentemente. También encontré esto http://www.protofunc.com/scripts/jquery/ajaxManager/ - obtuve algunas opciones más. –

1

La mayoría de los navegadores pueden manejar 6 o más solicitudes simultáneas de ajax a un solo dominio.
http://www.browserscope.org/?category=network&v=top

Si su secuencia de comandos coloca 30 solicitudes ajax a la vez, las primeras 6 solicitudes se llevarán a cabo muy rápidamente. Después de eso, el navegador puede comenzar a asignar períodos de espera arbitrarios de hasta 5 segundos. Chrome es un excelente ejemplo de este comportamiento.

Solicitudes 1-6 retorno en 5 ms.

Solicitudes 7-12 vuelven en 5,005 ms.

Solicitudes 11-18 vuelven en 10,005 ms.

Solicitudes 19-24 vuelven en 15,005 ms.

Solicitudes 25-30 vuelven en 20,005 ms.

Recomiendo crear una cola de devoluciones de funciones para manejar todas las solicitudes ajax de su aplicación y procesar no más de 6 de ellas a la vez.

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>

Cuestiones relacionadas