callback Funktionen – Funktionen als Argument von Funktionen

callback oder Rückruffunktionen: Asynchrone Verarbeitung und Erweiterung

Die Informatik nennt Funktionen, die einer anderen Funktion als Parameter übergeben werden, callback function – Rückruffunktion. callback-Funktionen werden nach der Ausführung einer anderen Funktion ausgeführt – daher der Name callback.

Bevorzugt verarbeiten Callback-Funktionen das Ergebnis einer asynchronen Funktion, aber callback-Funktionen werden auch oft in Librarys verwendet, weil sie Funktionen erweiterbar machen.

18-12-15 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

Objekte erster Klasse

Funktionen sind Objekte erster Klasse – wir können Funktionen als Argument in Funktionen übergeben (anders z.B. als in der Programmiersprache C, wo Funktionen nicht in Funktionen übergeben werden können). setTimeout ist ein ausgesprochen einfaches Beispiel einer callback-Funktion:

setTimeout ( function () {
	console.log('Genug gewartet');
}, 1000);
console.log('Wetten, ich werde Erster?');

Der erste Parameter ist eine Funktion, also eine Callback-Funktion. Javascript wartet nicht ab, sondern führt direkt die folgenden Zeilen aus.

[Log] Wetten, ich werde Erster? 
[Log] Genug gewartet 

setTimeout finden wir eher selten in freier Wildbahn. Viel häufiger begegnen wir Callback-Funktionen rund um dem XMLHttpRequest und beim EventListener.

function reqListener () {
	document.querySelector(".box").innerHTML = this.responseText;
}

var xhr = new XMLHttpRequest();

                             +-- Callback-Funktion
                             |             
xhr.addEventListener("load", reqListener);
xhr.open ("GET", "sometext.txt");
xhr.send ();

callback: Funktion als Argument von Funktionen

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 und allgemeingültig 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

Callback-Funktionen als anonyme Funktionen

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. Callback-Funktionen werden oft als anonyme Funktionen notiert.

var xhr = new XMLHttpRequest();

                             +--- Callback-Funktion als anonyme Funktion
                             |
xhr.addEventListener("load", function () { 
	document.querySelector(".box").innerHTML = this.responseText; 
});
xhr.open ("GET", "sometext.txt");
xhr.send ();

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

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

Das nutzen wir wieder und wieder: Wenn der Benutzer auf das Element klickt, wird die anonyme callback-Funktion aufgerufen.

Dieselbe Funktionalität, nur mit einer Funktion mit Namen:

elem.addEventListener ("click", handleClick);
… 
function handleClick() {
}

Beispiel Callback-Funktion

Javascript enthält Funktionen, die per Vorgabe asynchron ausgeführt werden. Dazu gehören z.B. Ajax-Funktionen wie der XMLHTTPRequest, setTimeout und requestAnimationFrame.

Oft sollen nach der Ausführung einer asynchronen Funktion andere Funktionen ausgeführt werden – dafür werden traditionell Callback-Funktionen als Argument eingesetzt.

So wird festgelegt, was ausgeführt werden soll, wenn die asynchrone Funktion abgearbeitet wurde. setTimeout hat z.B. zwei Parameter: eine Callback-Funktion und den Delay, die Verzögerung bis zur Ausführung.

setTimeout (callback, delay);

setTimeout (function () {
   console.log ("Das wars!");
}, 5000);

setTime wartet fünf Sekunden und ruft dann die Callback-Funktion auf, die Das wars! in die Console schreibt.

Callback – sobald ein HTML-Element geladen ist

Wenn das Script ausgeführt werden soll, sobald alle Objekte in das DOM geladen sind, sehen wir in jQuery typischerweise den Aufruf $(document).ready() oder die Kurzschrift $().

Für die Umsteiger von jQuery zum nativen Javascript ("Vanilla Javascript"): Das geht im reinen Javascript mit einem eventListener auf DOMContentLoaded.

let ready = (callback) => {
  if (document.readyState != "loading") callback();
  else document.addEventListener("DOMContentLoaded", callback);
}

ready(() => { 
  /* Jetzt ist das DOM vollständig geladen */ 
});

Promise und Callbacks

Ein Promise ist ein Konstrukt in Javascript, das festlegt, was passieren soll, wenn eine zeitgesteuerte Operation stattgefunden hat. Sie steuert ein Versprechen bei, um die Abläufe asynchroner Anweisungen zu vereinfachen.

Ein Promise wird nur einmal aufgelöst und mehrere Versprechen können einfach miteinander verkettet werden.