Besseres Verständnis der Rückruffunktionen in JavaScript


163

Ich verstehe es, eine Funktion als Rückruf an eine andere Funktion zu übergeben und ausführen zu lassen, aber ich verstehe nicht die beste Implementierung, um dies zu tun. Ich suche ein sehr einfaches Beispiel wie dieses:

var myCallBackExample = {
    myFirstFunction : function( param1, param2, callback ) {
        // Do something with param1 and param2.
        if ( arguments.length == 3 ) {
            // Execute callback function.
            // What is the "best" way to do this?
        }
    },
    mySecondFunction : function() {
        myFirstFunction( false, true, function() {
            // When this anonymous function is called, execute it.
        });
    }
};

Wenn ich in myFirstFunction einen neuen Rückruf () zurückgebe, funktioniert dies und führt die anonyme Funktion aus, aber das scheint mir nicht der richtige Ansatz zu sein.


Richtig in welchem ​​Sinne? In der Regel werden Rückrufe für Ereignishandler verwendet - insbesondere für asynchrone Ajax-Aufrufe - im Grunde Dinge, bei denen Sie nicht wissen, wann (oder ob) eine Antwort kommt.
Cletus

2
Übrigens sind Argumente Array-ähnlich, aber nicht Array, so dass Sie argument.length nicht ausführen können, aber Sie können es mit der Slice-Methode in ein Array konvertieren ...
Paul

1
@paul, obwohl Sie Recht haben, dass argumentses sich nicht um ein Array handelt, können Sie seine Länge dennoch wie folgt angeben: Probieren Sie es aus arguments.length. Diese Eigenschaft bezieht sich auf die Anzahl der tatsächlich übergebenen Argumente und nicht unbedingt auf die Anzahl der Parameter in der Funktionssignatur.
hotshot309

Antworten:


132

Das kann man einfach sagen

callback();

Alternativ können Sie die callMethode verwenden, wenn Sie den Wert thisinnerhalb des Rückrufs anpassen möchten .

callback.call( newValueForThis);

Innerhalb der Funktion thiswäre was auch immer newValueForThis.


91

Sie sollten überprüfen, ob der Rückruf vorhanden ist und eine ausführbare Funktion ist:

if (callback && typeof(callback) === "function") {
    // execute the callback, passing parameters as necessary
    callback();
}

Viele Bibliotheken (jQuery, Dojo, etc.) ein ähnliches Muster für ihre asynchronen Funktionen sowie node.js für alle Asynchron - Funktionen (NodeJS in der Regel passiert errorund dataan die Callback). Ein Blick in den Quellcode würde helfen!


Warum wirfst du callbackeinen String und überprüfst dann seinen Typ? Wird dies die Leistung verbessern? Dies ist wie das Überprüfen des Typs, das Überprüfen, ob der konvertierte Boolesche Wert true zurückgibt, und das erneute Überprüfen seines Typs und das Testen anhand der Zeichenfolge ... Können Sie erklären, warum?
KopfschmerzCoder

Ich bin neugierig, warum Sie die erste Behauptung für einen Rückruf benötigen ... ist es, null oder undefiniert zu überprüfen? Würden Sie das nicht typeof(callback)für Sie erreichen? typeof(null) === "Object",typeof("undefined") === "undefined"
PJH

1
Kurzschluss UND. Wenn der Rückruf nicht vorhanden ist, müssen Sie seinen Typ nicht berechnen. Aber du hast recht. Es wird mit dem typeof () nicht benötigt, aber ich werde ein jsperf machen und sehen, ob sich der Kurzschluss lohnt.
Arunjitsingh

@headacheCoder - callbackwird nicht in eine Zeichenfolge umgewandelt, sondern der Typ wird vor dem Aufruf überprüft, ob es sich um eine Funktion handelt. Der Code akzeptiert vermutlich callbackals Argument und ist sich nicht sicher, ob das Argument von einem aufrufbaren Typ ist - oder vielleicht sind die Argumente von verschiedenen Typen, um eine Form des Polymorphismus bereitzustellen, bei der Code möglicherweise unterschiedlich auf verschiedene typeofArgumente reagiert .
LeeGee

34

Es gibt 3 Hauptmöglichkeiten, um eine Funktion auszuführen:

var callback = function(x, y) {
    // "this" may be different depending how you call the function
    alert(this);
};
  1. Rückruf (Argument_1, Argument_2);
  2. callback.call (some_object, argument_1, argument_2);
  3. callback.apply (some_object, [argument_1, argument_2]);

Die von Ihnen gewählte Methode hängt davon ab, ob:

  1. Sie haben die Argumente in einem Array oder als unterschiedliche Variablen gespeichert.
  2. Sie möchten diese Funktion im Kontext eines Objekts aufrufen. In diesem Fall würde die Verwendung des Schlüsselworts "this" in diesem Rückruf auf das Objekt verweisen, das als Argument in call () oder apply () übergeben wurde. Wenn Sie den Objektkontext nicht übergeben möchten, verwenden Sie null oder undefiniert. Im letzteren Fall würde das globale Objekt für "dies" verwendet.

Dokumente für Function.call , Function.apply


6

Bei Rückrufen geht es um Signale und bei "Neu" geht es um das Erstellen von Objektinstanzen.

In diesem Fall wäre es noch angemessener, nur "callback ()" auszuführen. als "return new callback ()", weil Sie sowieso nichts mit einem Rückgabewert machen.

(Und der Argumentargument.length == 3-Test ist wirklich klobig, fwiw, besser zu überprüfen, ob der Rückrufparameter existiert und eine Funktion ist.)


6

Die richtige Implementierung wäre:

if( callback ) callback();

Dies macht den Rückrufparameter optional.


Was ist, wenn das Rückrufargument keine Funktion ist?
Yaki Klein

2

Sie können verwenden:

if (callback && typeof(callback) === "function") {
    callback();
}

Das folgende Beispiel ist etwas umfassender:

function mySandwich(param1, param2, callback) {
  alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
  var sandwich = {
      toppings: [param1, param2]
    },
    madeCorrectly = (typeof(param1) === "string" && typeof(param2) === "string") ? true : false;
  if (callback && typeof(callback) === "function") {
    callback.apply(sandwich, [madeCorrectly]);
  }
}

mySandwich('ham', 'cheese', function(correct) {
  if (correct) {
    alert("Finished eating my " + this.toppings[0] + " and " + this.toppings[1] + " sandwich.");
  } else {
    alert("Gross!  Why would I eat a " + this.toppings[0] + " and " + this.toppings[1] + " sandwich?");
  }
});


1

Hier ist ein grundlegendes Beispiel, das die callback()Funktion in JavaScript erklärt:

var x = 0;

function testCallBack(param1, param2, callback) {
  alert('param1= ' + param1 + ', param2= ' + param2 + ' X=' + x);
  if (callback && typeof(callback) === "function") {
    x += 1;
    alert("Calla Back x= " + x);
    x += 1;
    callback();
  }
}

testCallBack('ham', 'cheese', function() {
  alert("Function X= " + x);
});

JSFiddle


1

function checkCallback(cb) {
  if (cb || cb != '') {
    if (typeof window[cb] === 'undefined') alert('Callback function not found.');
    else window[cb].call(this, Arg1, Arg2);
  }
}

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.