callback Funktionen – Funktionen als Argument von Funktionen

callback oder Rückruffunktionen machen Javascript-Funktionen erweiterbar

Die Informatik nennt Funktionen, die einer anderen Funktion als Parameter übergeben werden, callback function – Rückruffunktion. callback-Funktionen werden vor allem in Librarys verwendet Inversion of Control, weil sie Funktionen erweiterbar machen.

callback-Funktionen werden nach der Ausführung einer anderen Funktion ausgeführt – daher der Name callback.

Funktionen sind Objekte erster Ordnung – wir können Funktionen als Argument in Funktionen übergeben.

Das ist ein ausgesprochen einfaches Beispiel einer callback-Funktion:

let x = function () {
   console.log ("Ich werden aus einer Funktion heraus aufgerufen");
}

let y = function (callback) {
   console.log("mach mal wieder was");
   callback();
}

y(x);
[Log] mach mal wieder was (callback-function.html, line 77)
[Log] Ich werden aus einer Funktion heraus aufgerufen (callback-function.html, line 73)

Bei einer callback-Funktion als Argument wird nicht das Ergebnis der Funktion x an Funktion y übergeben, sondern die Funktion selber, die dann an einer beliebigen Stelle ausgeführt wird. Vor oder nach dem callback können beliebige Anweisungen stehen.

Nehmen wir die einfache Funktion calc, die eine Operation je nach dem Wert von calcType durchführt:

let calc = function (num1, num2, calcType) {
   if (calcType === "add") {
      return num1 + num2; 
   } else if (calcType === "mult") {
      return num1 * num2; 
   }
}

calc (2, 3, 'add');
console.log ( calc(2, 3, 'add'));
[Log] 5 (callback-function.html, line 97)

Wenn calc Teil einer umfangreichen Library ist und addiert, multipliziert, teilt … usw., sollte die Funktion so abstrakt wie möglich gehalten und calcType als Argument aus der Funktion herausgehalten werden, damit wir später ohne Änderung weitere Operationen hinzugefügt werden können.

let add = function (a, b) {
	return a + b;
}

let multiply = function (a, b) {
	return a * b;
}

let calc = function (num1, num2, callback) {
	return callback (num1, num2);
}

console.log (calc (2, 3, add));

Jetzt kann ich die Library jederzeit um neue Operationen ergänzen, ohne dabei calc anzufassen. Ein Beispiel:

let machWasAnderes = function (a, b) {
   console.log (`Hier sind deine beiden Zahlen ${a}, ${b}`);
}
Hier sind deine beiden Zahlen 2, 3

Anonyme Funktionen

Das könnte auch so geschrieben werden:

console.log (calc (2, 3, function (a, b) { 
   return a - b; 
}));

Wenn eine Funktion nur einmal gebraucht wird, kann sie auch direkt übergeben werden. Da die Funktion keinen Namen hat, wird sie auch als anonyme Funktion bezeichnet.

Eine häufig verwendete Variation der anonymen Funktion ist z.B. addEventListener:

addEventListener ("click", function () {
})

typeof – function

typeof prüft, ob der Benutzer tatsächlich eine Funktion übergibt.

let calc = function (num1, num2, callback) {
   if (typeof callback === "function") {
      return callback (num1, num2);
   }
}

Beispiel Callback-Funktion

Die Umwandlung eines Bitmap-Bildes in eine Data-URL ist ein Beispiel für die Anwendung von callback-Funktionen. getDataUri nimmt die URL eines Bildes und erzeugt

/** https://davidwalsh.name/convert-image-data-uri-javascript **/

function getDataUri(url, callback) {
    let image = new Image();

    image.onload = function () {
        let canvas = document.createElement('canvas');
        canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
        canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size

        canvas.getContext('2d').drawImage(this, 0, 0);

        // Get raw image data
        callback(canvas.toDataURL('image/png').replace(/^data:image\/(png|jpg);base64,/, ''));

        // ... or get as Data URI
        callback(canvas.toDataURL('image/png'));
    };

    image.src = url;
}

getDataUri wird aufgerufen mit der Adresse des Bildes und einer der callback-Funktion, in der das Bild behandelt wird – in diesem Beispiel in ein PDF platziert.

getDataUri("p01-Fraisier.jpg", function(dataUri) {
    pdf.addImage(dataUri,'JPEG', 20, 40, 40, 54);
      
});
callback function