Nicht selten wünscht man sich, von seinen AJAX-Responses , dass sie in der gleichen Reihenfolge ankommen, in der die Anfragen abgesendet wurden bzw. zumindest in der selben Reihenfolge in der sie beim Server verarbeitet wurden (z.B.: Warenkorb). In anderen Fällen ist dagegen klar, dass eine Antwort auf eine Anfrage keinen Sinn mehr macht, da der User sich – während der Verarbeitung des XHR-Requests – entschieden hat einen anderen Beitrag auszuwählen.
Aufgrund der Asynchronität von AJAX, schwankender Latency sowie unterschiedlich langer Verarbeitung durch serverseitige Scripte kann dies jedoch nicht vorausgesetzt werden. Um derartige sowie ähnliche AJAX-Anfragen zu behandeln, habe ich ein kleines jQuery-Plugin zum managen von AJAX geschrieben.
Mit diesem Script lassen sich AJAX-Anfragen queuen, abbrechen blocken sowie AJAX-Antworten synchronisieren. Zum $.ajaxManager.
Hi Alexander,
danke fuer deine Arbeit! Habe dein Plugin erfolgreich im Einsatz,
es klappt super! Eigentlich sollte jQuery diese Funktionalitaet
im Core haben, denn mehrere parallelle Ajax-Requests sind mitunter
ja keine Seltenheit…
Gruss,
Falk
Comment by Falk Pauser — July 9, 2008 @ 1:24 am
danke für die Blumen. jQuery hat das wahrscheinlich deshalb nicht im Core, weil Ajax – entgegen des Hypes – im täglichen JS-Geeschäft relativ selten genutzt wird und bei Verwendung häufig unsinnige Doppelrequests, überholende Requests vernachlässigt werden.
Es kann aber sehr gut sein, dass soetwas ähnliches entweder im jQuery-Core oder im UI-Core landen wird. Eine zukünftige Version von jQuery wird ein Autocomplete/Combobox-Plugin beinhalten. Das autocomplete-Plugin von Jörn Zäfferer (http://bassistance.de/2008/06/25/release-autocomplete-plugin-101/) wird hier wahrscheinlich Grundlage sein und dieses setzt wiederum das Ajax-Queue-Plugin (http://plugins.jquery.com/project/ajaxqueue).
Comment by alexander farkas — July 27, 2008 @ 5:10 am
In Ajax Manager you do something like:
q[num].fnError.apply($, q[num].error);
but it should be:
q[num].fnError.apply(q[num], q[num].error);
In original ajax requests from jQuery ‘this’ in callback functions points to options not to jquery object.
Comment by Rafał Jońca — December 8, 2008 @ 4:36 am
Sehr nett.
‘blockSameRequest’ hat nicht genau zu _meinem_ gewünschten Zeil geführt. Ich wollte den _letzten_ selben Request blocken (da die Abfrage (bei mir) dann überflüssig wird…
…
manageAjax: function(o){
o = $.extend({
manageType: ‘normal’,
maxReq: 0,
blockSameRequest: false,
blockSameLastRequest: false,
lastRequest: false,
global: true
}, o);
…
…
if (s.blockSameLastRequest) {
var lr = this.lastRequest;
if (lr && lr.data === cD && lr.url === o.url && lr.type === o.type) {
return false;
}
}
this.lastRequest = q[quLen] = {
…
Comment by derGrubeler — December 10, 2008 @ 6:01 am
Thx, for pointing this out. I had already fixed this issue, but had no time to update my plugins. I will try to do this this weekend.
Comment by alexander farkas — December 10, 2008 @ 12:52 pm
Werstehe ich dich richtig, wenn request a ausgelöst wurde, dann ein request b und dann wieder ein request a, dann soll der 2. request a nicht geblockt werden, obwohl der 1. noch gar nicht beantwortet wurde?
Für welchen usecase, brauchst du das? Oder ist dort ein Bug verborgen?
Comment by alexander farkas — December 10, 2008 @ 12:56 pm
Nein, dafür ist das nicht gedacht (darum kümmert sich ja das ‘blockSameRequest’ – wenn gewünscht).
Beispiel: warenkorb-Forumlar. Bei jeder Änderung (Anzahl, zusatz Optioen,..) soll ein Request geschickt werden. Leider funnktioniert das (dank IE) nicht mit $(element).change(). Ich brauch also noch andere (nicht eindeutige) trigger (focus,click). Damit jetzt nicht ständig der selben Warenkorb aktualisieret wird (problemlos, aber eben auch sinnlos), prüfe ich auf den _letzten_ (auch wenn der schon 10 sec alt und fertig war). Könnt ich natürlich auch auserhalb des managers machen, aber wenn ich schon einen “Manager” habe
– hatte schon öffters diese Situation.
Macht natürlich nur bei “abortOld” bzw. “sync” Sinn.
——-
Noch was:
Laut doc soll $.ajaxManager “jQuery-Ajax-Options” annehmenen.
Soweit ich sehe ist das aber nicht der Fall:
var am = $.manageAjax({type: ‘POST’,manageType: …});
am.add({data: “something”,…});
//macht eine default GET-Abfrage
..oder ich hab den Sinn darin nicht verstanden
Comment by derGruebler — December 11, 2008 @ 6:30 am
@4:
“lastRequest: false” kommt natürlich nicht in die options, sondern gehört zum ajaxManager:
ajaxManager: function(o){
this.lastRequest = false;
…
}
Comment by derGruebler — December 11, 2008 @ 6:42 am
Zu.: lastRequest/change-Event
ah, ich verstehe es ist eigentlich ein Formular-Event Problem. Darüber wollte ich mich auch mal auslassen. Die Formular-Events, insbesondere das change-Event, sind der letzte Dreck.
Beim change Event hält sich der IE übrigens eher an den W3C Standard als andere Browser (Ausnahme: select-DropDowns bei Tastaturbenutzung). Die Spezifikation des change Events ist soetwas von …
Wenn es um ein change bei checkboxen und radiobuttons geht. Sollte eigentlich ein click-Event ausreichen. Du brauchst hier also kein zusätzliches change/focus-Event. Damit sollte dein Problem behoben sein.
Ich setze hier in der Firma ein custom-Change-Event ein, welches ein intuitives, cross-browser-taugliches change-Event einführt. Wenn ich etwas Zeit habe, poste ich das mal…
Zu.: options
Nein, das Script macht das nicht. Das war ein Kopierfehler in der Doku. Aber ich ziehe hier das Script mal am Wochenende nach, weil macht ja wirklich Sinn.
Comment by alex@arbeit — December 11, 2008 @ 9:24 am
@alex:
> Sollte eigentlich ein click-Event ausreichen.
Danke. Du hast natürlich recht. Frag mich nicht wieso ich der Meinung war ich brauch nochmals ein focus (für Tastatur) und ein weiteres click für die entsprechenden Labels. Kam mir wohl einfach zu einfach vor
. Dabei hab ich das sicher mehrmals getestet – auf x browsern. Komisch, jetzt funktioniert das überall…. naja soll vorkommen.
Nochmals Danke für die Klarstellung – und sorry für die leicht Off-Topic.
Comment by derGruebler — December 11, 2008 @ 11:58 am
Hi,
The Ajax manager http://www.protofunc.com/scripts/jquery/ajaxManager/ is just what I was looking for – well almost.
My case is that I’m returning filter results as you type, narrowing down a list of records. The filter text is sent on each keypress. However, in some (uncommon) situations, the server can be a bit slow, taking say 1/2 a second to return a result for each keypress which is a lot slower than you can type. Rather than send every keypress to the server, putting more load on it, I’d like to wait until the current request completes, then send the newest request only. NB this is different to sending every request and aborting old ones. I hope the way I’ve explained this makes sense.
I’ve modified the code to do what I want but due to my lack of Javascript knowledge it may not be the best written in the world. Can I send it to you anyway to see if you’d like to integrate or rewrite (or ignore)?
Best regards
Comment by Oliver Kohll — January 8, 2009 @ 8:23 am
p.s. my email is oliver at gtwm dot co dot uk
Comment by Oliver Kohll — January 9, 2009 @ 12:07 pm
Hi
When I use this plugin I am getting a memory leak in IE6. Has anyone else experienced this?
I am using these parameters:
var ajaxManager = $.manageAjax({ manageType: ‘abortOld’, maxReq: 0 });
Thanks
Ben
Comment by ben — March 3, 2009 @ 9:44 am
I think I got some result. Thank you here.
Comment by wpdigger — June 3, 2009 @ 2:48 am
How can this be used in a batch mode? I want to define several ajax requests at once, then fetch the entire batch (processing order isn’t important) and then execute a function when all requests in the batch have completed.
Comment by Mike — August 5, 2009 @ 11:06 am
jQuery has already an ajaxStop-Event for this. I added something similiar in version 2.5.
Here is an example:
//create an ajaxmanager
$.manageAjax.create(‘queue’, {queue: true});
//add a stop listener
$(document).bind(‘queueStop’, function(e, data){
//data is an array of objects
// the objects have two properties
//1. an reference to the xhr object, called xhr
//2. the status text, called status
// try console.log(data)
});
//add some ajaxQueues
$.manageAjax.add(‘queue’, {url: ‘bla.html’});
$.manageAjax.add(‘queue’, {url: ‘blub.html’});
I hope this helps.
Comment by alexander farkas — August 9, 2009 @ 3:34 am
Hallo Alexander,
ich würde gerne dein Plugin zum Laden von images im Hintergrund verwenden. Leider wird die complete-Funktion ausgelöst, obwohl das Bild noch gar nicht komplett geladen wurde. Habe zum Testen die Bandwidth (mit mod_bw) für die Bildquelle reduziert um so das Laden der Bilder zu simulieren. Wäre das Problem gelöst, könnte man nette Apps bauen, die aufgrund der Queue jederzeit steuerbar bleiben.
Hast du vielleicht eine Idee?
Grüße, Sven
Comment by Sven Wappler — March 11, 2010 @ 2:26 pm