Wann würde ich JQuery.Callbacks verwenden?

Lesezeit: 11 Minuten

Benutzer-Avatar
Keith. Abramo

Ich habe neue Sachen durchgesehen, die zu jQuery 1.7 hinzugefügt wurden, und ich habe gesehen, dass sie jetzt jQuery.Callbacks() haben. http://api.jquery.com/jQuery.Callbacks/.

Die Dokumentation zeigt Ihnen, wie Sie jQuery.callbacks() verwenden, aber keine anwendbaren Beispiele dafür, wann ich sie verwenden möchte.

Es scheint, dass Sie Callbacks aus einer Callback-Liste hinzufügen/entfernen können, und Sie können jQuery.callbacks().fire(args) ausführen, aber dies löst nur ALLE Callbacks in dieser Liste aus. Vielleicht übersehe ich etwas, aber das scheint nicht sehr nützlich zu sein.

Als ich diese neue Funktionalität zum ersten Mal sah, dachte ich, Sie könnten sie mit Schlüssel/Wert-Paaren verwenden. Dies würde dann eine einfache Möglichkeit bieten, Callback-Funktionen an einem einzigen Ort in Ihrer Anwendung zu verwalten. Etwas wie

$.callbacks.add("foo", myFunction);

und dann zum Beispiel, wenn ich diesen Rückruf am Ende meiner Funktion aufrufen wollte, könnte ich so etwas tun

$.callbacks().fire("foo", args);

Es sieht jedoch nicht so aus, als könnten Sie bestimmte Rückrufe auslösen, Sie können nur alle mit den angegebenen Argumenten oder keines davon auslösen.

Was mir am nächsten kam, war die Möglichkeit, der Funktion .fire() einen Kontext zu geben, um die Eigenschaft “this” festzulegen

.fireWith(context, args)

aber das hilft auch nicht wirklich weiter.

  1. Verstehe ich die Dokumentation falsch?

  2. Wenn dies die gewünschte Funktionalität ist, was sind einige anwendbare Beispiele, wo dies nützlich ist.

  • Sie müssen zuerst ein Callback-Objekt erstellen, indem Sie so etwas tun var callbacks = $.Callbacks();. Dann können Sie Methoden mit hinzufügen callbacks.add(myFunction); (Sie benennen sie nicht, Sie fügen nur Funktionen zu einer Liste hinzu). Sie werden dann (der Reihe nach) von abgefeuert callbacks.fire(args). fireWith wird verwendet, um einen Kontext zu setzen (this), aber nicht auswählen, welcher Rückruf ausgelöst werden soll. fireWith erfordert auch, dass die Argumente ein Array sind, zum Beispiel: callbacks.fireWith(document, "foo");.

    – generisch

    9. November 2011 um 21:11 Uhr


  • @Rocket Ich habe den Kontextfehler behoben, den ich in meiner Erklärung hatte. Ich verstehe, dass Sie alle Rückrufe auf einmal mit Feuer aufrufen und ihnen alle die gleichen Argumente geben können, aber das scheint nicht hilfreich zu sein. Wann möchte ich so etwas in meiner Bewerbung machen? Warum gibt es keine Funktion zum Auslösen bestimmter Rückrufe? Welches Problem löst diese neue Funktionalität?

    – Keith. Abramo

    9. November 2011 um 21:11 Uhr

  • Ganz oben in der Dokumentation steht: „Die Funktion $.Callbacks() ist intern verwendet ….“ Mit anderen Worten, Sie – als Entwickler, der ist nicht am jQuery Core arbeiten – wird wirklich keinen praktischen Nutzen dafür haben, aber sie dokumentieren es trotzdem, um Fragen wie die, die Sie gerade gestellt haben, zu vermeiden.

    – Brandstifter

    9. November 2011 um 21:17 Uhr

  • Ja, es heißt, es wird intern verwendet … es heißt auch: “Es kann als ähnliche Basis verwendet werden, um die Funktionalität für neue Komponenten zu definieren.” Was Sie bestätigen könnten, indem Sie jsFiddle starten und alert($.Callbacks) ausführen, was zeigen würde, dass es für Sie als Entwickler verfügbar ist. Was meine Frage immer noch gültig macht. Wenn es über ihre API für mich verfügbar gemacht wird. Ich würde gerne praktische Anwendungen kennenlernen.

    – Keith. Abramo

    9. November 2011 um 21:23 Uhr

  • Es scheint, dass diese ‘Callback’-Kette dem Erstellen einer Warteschlange von Funktionen ähnelt und sie jeweils die nächste aufrufen, nachdem sie fertig sind. Nur dass die Funktionen in der Warteschlange bleiben und Sie den Kontext festlegen können.

    – generisch

    9. November 2011 um 21:48 Uhr


Benutzer-Avatar
Naftali

Um die @Rockets-Antwort ein wenig zu erweitern und einige Verwirrung zu beseitigen:

Der Grund, warum man möglicherweise jQuery verwenden muss $.Callbacks ist facettenreich:

  1. Der Benutzer hat viel Code in einer Funktion und möchte ihn aufteilen
  2. Sie nehmen diese Informationen und senden sie über die jQuery-Callback-Funktion, die es ihnen dann ermöglicht, ihren Code in besser handhabbare Teile aufzuteilen, mit denen sie arbeiten können.
    Also (zum Beispiel) wenn man sich anschaut @ Rockets Code:

    var clickCallbacks = $.Callbacks();
    
    clickCallbacks.add(function() { //one one function piece
        //parse and do something on the scope of `this`
        var c = parseInt(this.text(), 10);
        this.text(c + 1);
    });
    clickCallbacks.add(function(id) { //add a second non-related function piece
        //do something with the arguments that were passed
        $('span', '#last').text(id);
    });
    
    $('.click').click(function() {
        var $ele = $(this).next('div').find('[id^="clickCount"]');
        clickCallbacks.fireWith($ele, [this.id]); //do two separate but related things.
    });
    
  3. Was Sie jetzt haben können, sind mehrere Callback-Batches von Funktionen, die Sie jetzt aufrufen können, wann immer Sie es für notwendig halten, ohne so viele Änderungen im gesamten Code vornehmen zu müssen.

  • @Rocket jederzeit ^_^ Danke, dass du es mir etwas erklärt hast 😀

    – Naftali

    9. November 2011 um 21:47 Uhr

  • Ahhh OK. Die “mehreren Callback-Batches” sind der SCHLÜSSEL, den ich glaube, ich habe gefehlt. Erstellt $.Callbacks also eine Instanz einer Callbacks-Liste? Ich könnte also Callbacks1 und Callbacks2 haben, die dann unterschiedliche, aber verwandte Callback-Funktionen enthalten würden? Also könnte ich dann callbacks1.fire() in myFunction1 und callbacks2.fire() in myFunction2 aufrufen?

    – Keith. Abramo

    9. November 2011 um 22:09 Uhr

  • @Keith.Abramo, das ist mein Eindruck von dem, was es tut. Sie sollten testen, um sicherzugehen. Im Grunde was $.Callbacks() gibt ein Objekt zurück, das Sie dann verwenden können, um es Ihren Bedürfnissen anzupassen.

    – Naftali

    9. November 2011 um 22:10 Uhr


  • @Keith.Abramo: Ja, Sie können verschiedene Rückruflisten haben. var c1 = $.Callbacks(), c2 = $.Callbacks();. Jeder Anruf an $.Callbacks() erstellt ein neues Objekt.

    – generisch

    9. November 2011 um 22:12 Uhr

  • Genial. Das klärt sich super auf. Hier ist ein jsFiddle für diejenigen, die in Zukunft darauf stoßen und eine Überprüfung wünschen jsfiddle.net/UX5Ln/1

    – Keith. Abramo

    9. November 2011 um 22:15 Uhr

Benutzer-Avatar
generisch

Ich kann sehen, dass Rückrufe nützlich sind, wenn Sie verschiedene DOM-Elemente mit denselben Methoden aktualisieren.

Hier ist ein kitschiges Beispiel: http://jsfiddle.net/UX5Ln/

var clickCallbacks = $.Callbacks();

clickCallbacks.add(function() {
    var c = parseInt(this.text(), 10);
    this.text(c + 1);
});
clickCallbacks.add(function(id) {
    $('span', '#last').text(id);
});

$('.click').click(function() {
    var $ele = $(this).next('div').find('[id^="clickCount"]');
    clickCallbacks.fireWith($ele, [this.id]);
});

Es aktualisiert den Klickzähler und den „zuletzt geklickten“ Wert, wenn Sie auf etwas klicken.

  • Wow. Wie funktioniert diese zweite Callback-Funktion? (Ich habe mich noch nicht viel mit 1.7 befasst)

    – Naftali

    9. November 2011 um 21:27 Uhr

  • Ich benutze fireWith das ist wie telefonieren apply. jQuery ruft die Rückrufe mit meinem Kontext (einem jQuery-Objekt) und einem Argumentarray (das eine Zeichenfolge enthält) auf. Beide Callback-Funktionen werden aufgerufen. Der erste ignoriert die Argumente und verwendet this (das ist ein jQuery-Objekt). Der zweite wird nicht verwendet thisverwendet aber die übergebenen Argumente.

    – generisch

    9. November 2011 um 21:30 Uhr


  • Ich brauchte eine Weile, um zu verstehen, wie $.Callbacks hat funktioniert. Ich musste die Dokumentation mehrmals lesen.

    – generisch

    9. November 2011 um 21:34 Uhr

  • Roket – diese Antwort ist sehr, sehr nützlich und hat zu meiner Antwort beigetragen, aber Ihre Geige könnte jeden Moment tot sein und diese Antwort wird nutzlos. Könnten Sie Ihrer Antwort einen Code (oder den gesamten Code) aus Ihrer Geige hinzufügen, damit dies in Zukunft nützlich ist, wenn / falls die Geige tot ist?

    – Naftali

    10. Juli 2013 um 13:07 Uhr


Benutzer-Avatar
edsioufi

Ein (fast) sofort einsatzbereites jQuery Pub/Sub-System

Dies ist IMHO die interessanteste Anwendung, und da war es nicht deutlich In den Antworten angegeben (obwohl einige auf die Verwendung anspielen), füge ich es diesem relativ alten Beitrag hinzu.

Hinweis: Die Verwendung ist anhand eines Beispiels in der deutlich angegeben jQuery-Dokumentationaber ich denke, es wurde hinzugefügt, nachdem die Frage gepostet wurde.

Pub/subauch bekannt das Beobachtermusterist ein Muster, das fördert lose Kopplung und Einzelverantwortung in einer Bewerbung. Anstatt dass Objekte direkt die Methoden anderer Objekte aufrufen, abonnieren Objekte stattdessen eine bestimmte Aufgabe oder Aktivität und werden benachrichtigt, wenn sie auftritt. Eine ausführlichere Erläuterung der Vorteile der Verwendung des Pub/Sub-Musters finden Sie unter Warum sollte man das Publish/Subscribe-Muster (in JS/jQuery) verwenden?.

Sicher, das war mit benutzerdefinierten Ereignissen möglich trigger, .on() und .off()aber ich finde jQuery.Callbacks sein viel geeigneter für die Aufgabe und erzeugt saubereren Code.

Hier ist das Beispiel-Snippet aus der jQuery-Dokumentation:

var topics = {};
 
jQuery.Topic = function( id ) {
    var callbacks,
        method,
        topic = id && topics[ id ];
 
    if ( !topic ) {
        callbacks = jQuery.Callbacks();
        topic = {
            publish: callbacks.fire,
            subscribe: callbacks.add,
            unsubscribe: callbacks.remove
        };
        if ( id ) {
            topics[ id ] = topic;
        }
    }
    return topic;
};

Und ein Anwendungsbeispiel:

// Subscribers
$.Topic( "mailArrived" ).subscribe( fn1 );
$.Topic( "mailArrived" ).subscribe( fn2 );
$.Topic( "mailSent" ).subscribe( fn1 );
 
// Publisher
$.Topic( "mailArrived" ).publish( "hello world!" );
$.Topic( "mailSent" ).publish( "woo! mail!" );
 
// Here, "hello world!" gets pushed to fn1 and fn2
// when the "mailArrived" notification is published
// with "woo! mail!" also being pushed to fn1 when
// the "mailSent" notification is published.
 
/*
output:
hello world!
fn2 says: hello world!
woo! mail!
*/

Benutzer-Avatar
Frédéric Hamidi

Es scheint, dass $.Callbacks begann als Implementierungsdetail: ein Mittel, um Funktionslisten zu verwalten und alle Funktionen in einer gegebenen Liste mit denselben Argumenten aufzurufen. Ein bisschen wie C# Multicast-Delegiertemit zusätzlichen Funktionen, wie den Flags, die Sie übergeben können, um das Verhalten der Liste anzupassen.

Ein gutes Beispiel könnte sein, dass jQuery verwendet $.Callbacks intern zu implementieren ready Veranstaltung. bindReady() initialisiert eine Rückrufliste:

readyList = jQuery.Callbacks( "once memory" );

Beachten Sie das once und memory Flags, die sicherstellen, dass die Callback-Liste nur einmal aufgerufen wird und dass Funktionen, die hinzugefügt werden, nachdem die Liste aufgerufen wurde, sofort aufgerufen werden.

Dann, ready() fügt den angegebenen Handler zu dieser Liste hinzu:

ready: function( fn ) {
    // Attach the listeners
    jQuery.bindReady();

    // Add the callback
    readyList.add( fn );

    return this;
}

Schließlich wird die Rückrufliste ausgelöst, wenn das DOM bereit ist:

readyList.fireWith( document, [ jQuery ] );

All die ready Handler werden im Kontext desselben Dokuments mit derselben Referenz auf das globale jQuery-Objekt aufgerufen. Sie können nur einmal aufgerufen und an weitere Handler übergeben werden ready() wird von da an sofort angerufen, all dies mit freundlicher Genehmigung von $.Callbacks.

Ich sehe keine spezifische Erwähnung des Festlegens von Kontext, aber da Sie eine beliebige Anzahl von Argumenten übergeben können, wäre dies möglicherweise nützlich. Sie könnten auch Ihre eigene Konvention erstellen, um ein Flag als erstes Argument zu übergeben und Listener sofort false zurückgeben zu lassen, wenn sie die verbleibende Argumentliste nicht verarbeiten sollen.

Ich bin auf Fälle gestoßen, in denen so etwas nützlich gewesen sein könnte, aber ich habe stattdessen bind() und trigger() mit benutzerdefinierten Ereignissen verwendet. Stellen Sie sich ein Nachrichtenverarbeitungssystem vor (ein webbasierter Chatroom oder E-Mail-Client), bei dem Sie einen Dienst nach neuen Nachrichten abfragen. Eine Funktion könnte das Setzen einer Zahl in einer Spanne oder das Anzeigen eines Knurrens sein, wenn etwas passiert. Ein anderer könnte ein Raster aktualisieren. Mit Triggern müssten Sie das Ereignis für jeden Listener auslösen und die übergebenen Argumente von eventData “entrollen”, mit Rückrufen ist es nur ein Feuer und Ihre Listener sind einfache Javascript-Funktionen mit einer einfachen Argumentliste.

Rückrufe sind nicht gerade revolutionär, aber sie sorgen für weniger und saubereren Code.

  • Ich verstehe, wie Sie diese Funktionalität nutzen konnten, solange Sie nur EINEN Ort hatten, an dem ALLE Rückrufe aufgerufen werden mussten. Aber das ist in einer Webanwendung fast nie der Fall. Meistens haben Sie mehrere Funktionen, die Rückrufe erfordern, oder bedingte Situationen, in denen Sie möglicherweise einen Rückruf über einen anderen aufrufen möchten. Dies scheint mit dieser Architektur nicht möglich zu sein. Es sieht so aus, als wäre das Einzige, was Sie gewinnen, eine Möglichkeit, eine .fire () -Zeile anstelle von ein paar Aufrufen Ihrer Rückrufe aufzurufen. Auch Ihre Rückrufe müssen alle die gleichen Argumente verwenden.

    – Keith. Abramo

    9. November 2011 um 20:58 Uhr

  • Der Verweis auf den Kontext befindet sich in der Funktion .fireWith(). Tut mir leid, dass ich mich vertippt habe, aber ich habe es korrigiert.

    – Keith. Abramo

    9. November 2011 um 20:59 Uhr

Benutzer-Avatar
AutoSponge

Ich arbeite an einer App mit viel Geschäftslogik und mindestens 11 externen Diensten. Es hilft wirklich, die Dinge klar zu halten, wenn Sie Ihre eigenen Flusssteuerungsklassen und Verhaltensweisen schreiben können, indem Sie so etwas wie Callbacks verwenden, anstatt zu versuchen, der Deferred-Implementierung Ihren Willen aufzuzwingen.

  • Ich verstehe, wie Sie diese Funktionalität nutzen konnten, solange Sie nur EINEN Ort hatten, an dem ALLE Rückrufe aufgerufen werden mussten. Aber das ist in einer Webanwendung fast nie der Fall. Meistens haben Sie mehrere Funktionen, die Rückrufe erfordern, oder bedingte Situationen, in denen Sie möglicherweise einen Rückruf über einen anderen aufrufen möchten. Dies scheint mit dieser Architektur nicht möglich zu sein. Es sieht so aus, als wäre das Einzige, was Sie gewinnen, eine Möglichkeit, eine .fire () -Zeile anstelle von ein paar Aufrufen Ihrer Rückrufe aufzurufen. Auch Ihre Rückrufe müssen alle die gleichen Argumente verwenden.

    – Keith. Abramo

    9. November 2011 um 20:58 Uhr

  • Der Verweis auf den Kontext befindet sich in der Funktion .fireWith(). Tut mir leid, dass ich mich vertippt habe, aber ich habe es korrigiert.

    – Keith. Abramo

    9. November 2011 um 20:59 Uhr

1245160cookie-checkWann würde ich JQuery.Callbacks verwenden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy