18oct.2009
Ajax Queue avec jQuery
En travaillant sur un nouvel outil ce week-end, je me suis rendu compte que l'utilisation des queues en Ajax avec jQuery n'était pas natif.
Il existe quelques pistes à ces adresses, mais rien de vraiment pratique :
Puis j'ai trouvé une version plus intéressante de celui-ci dans le plugin jQuery Autocomplete, néanmoins, même si la fonction ABORT fonctionne correctement, mes appels en queue ne fonctionnaient pas.
J'en ai donc légèrement modifié les sources, en ajoutant un mode DEQUEUE me permettant de lancer la liste d'attente en fin de boucle par exemple.
Grâce à l'utilisation de la variable PORT, on peux ainsi contrôler indépendamment plusieurs queues, ou annuler des requêtes spécifiques, le tout en utilisant la fonction Ajax de jQuery.
Le plugin
/** * Ajax Queue Plugin */ (function($) { var ajax = $.ajax; var pendingRequests = {}; $.ajax = function(settings) { settings = jQuery.extend( settings, jQuery.extend( {}, jQuery.ajaxSettings, settings ) ); var port = settings.port; switch(settings.mode) { case "abort": if ( pendingRequests[port] ) { pendingRequests[port].abort(); } return pendingRequests[port] = ajax.apply(this, arguments); case "queue": var _old = settings.complete; settings.complete = function(){ if ( _old ) _old.apply( this, arguments ); jQuery([ajax]).dequeue("ajax" + port ); }; jQuery([ ajax ]).queue("ajax" + port, function(){ ajax( settings ); }); return; case "dequeue": jQuery([ajax]).dequeue("ajax" + port ); return; } return ajax.apply(this, arguments); }; })(jQuery);
Utilisation de la méthode ABORT
$input.bind('keyup', function(event) { if($searchTimeout != undefined) { clearTimeout($searchTimeout); } $searchTimeout = setTimeout(function() { $searchTimeout = undefined; var inputVal = $input.val().replace(/^\s+/g,'').replace(/\s+$/g,''); $.ajax({ mode : 'abort', port : 'ajaxSuggestions', type : 'POST', url : 'test.php', data : { 'keywords': inputVal }, success : function(msg) { alert(msg); } }); }, 500); });
Cette méthode est plus qu'intéressante dans le cas par exemple ou l'on souhaite afficher des informations au fur et à mesure que l'utilisateur écrit une information. Les requêtes précédentes utilisant le même port sont annulées au profit de la nouvelle requête, évitant un engorgement des informations et des erreurs dans le cas ou une requête ultérieure soit plus rapide que les précédentes.
Utilisation de la méthode QUEUE
for( i = 0 ; i <= 10 ; i++ ) { $.ajax({ mode: 'queue', port: 'ajaxWhois', type: 'POST', url: 'test.php', data: { 'increment': i }, success: function(msg){ alert(msg); } }); } $.ajax({ mode: 'dequeue', port: 'ajaxWhois' });
La méthode queue permet de boucler facilement sur plusieurs requêtes et ne les lancer qu'au moment choisit. Les requêtes ainsi lancées, le sont les unes à la suite des autres, évitant un engorgement des données reçues.
Commentaires
30/10/2009 | 13:43
Après avoir essayer de travailler avec le plugin, j'ai constaté que "abort" ne servait pas à grand chose ... en effet pendingRequests ne contient que la référence au dernier appel en mode "abort"...
j'ai donc opté pour une solution plus radicale.
case "abort":
jQuery(ajax).queue("ajax" + port, );
settings.mode='queue';
$.ajax(settings);
jQuery(ajax).dequeue("ajax" + port);
return;
Si je suis en mode "abort" alors :
1. je vide la pile (en passant un tableau vide)
2. je passe en mode "queue"
3. j'ajoute l'appel à la pile fraichement remise à zéro
4. et je dépile la file d'attente
Pour mon test, j'empile environ 200 appel ajax à enchainer, je les lances. A n'importe quel moment je peux lancer un abort.
Avec la version initiale je voyais simplement passer ma requête en mode abort au milieu du reste
Avec la version modifié, la dernière requête en cours termine son exécution, ma requête d'interruption est lancé immédiatement après. Une ceci fait, la pile étant vide plus rien ne se passe tant que je n'ai pas relancé un séquence.
En espérant que cela puisse aider qui que ce soit.
30/10/2009 | 13:51
je viens de remarquer un effet de bord si on enchaine un abort avec une mise en pile ... les deux requetes sont lancé en même temps
le principe de lancer une requete ajax pour vider la pile (même si on ne souhaite pas lancer réélement de requete) ne me plaisant pas je me suis tourné vers le plugin ajaxq disponible sur Google Code
http://code.google.com/p/jquery-aja...
au lieu d'appeler $.ajax(settings) on appel $.ajaxq(nomDeLaPile, settings)
Le plugin tourne très bien et parfaitement remplis sur role sur l'ensemble de mes tests
2/11/2009 | 13:19
En effet les deux n'ont aucun lien entre eux ^^
Ni dans ma version ni dans celle de base, ce qui est expliqué dans le billet. La méthode abort permet de fermer un port pour passer une autre requête. Et la méthode apply applique les nouvelles données.
Il est vrai qu'une fonction clearQueue serait un plus, mais ce n'est pas un abort. L'abort termine toute connexion active. Vider une queue ne signifie pas forcement bloquer les requêtes en cours.