Javascript async / await

async-await

Nach Callbacks und Promisses ist async / await eine intuitive und gut lesbare Technik zur Steuerung asynchroner Events. Das Besondere an async / await: Auch wenn die Ausführung asynchron abläuft, bleibt der Scriptcode besser organisiert und lesbarer.

18-12-15 SITEMAP

Wenn setTimeout nicht wartet

Wenn wir einen Timeout einsetzen, stellen wir uns einen einfachen Ablauf vor. Ein Counter soll jeweils mit einem delay von 1 Sekunde bis 5 zählen, dabei nach der "2" eine Pause – delay – von drei Sekunden einlegen.

Mit dem linear und eigentlich verständlichen Script funktioniert der Counter nicht: Er spring sofort auf 5: setTimeout läuft asynchron, die Zeilen unter den Aufrufen von delay werden sofort ausgeführt.

Ohne async / await
const delay = seconds => {
	return new Promise (
		resolve => setTimeout (resolve, seconds * 1000)
	)
};

const countToFive = () => {
	console.log ("0 Sekunden");
	count.textContent = "0";
	 delay (1);
	console.log ("1 Sekunde");
	count.textContent = "1";
	 delay (1);
	console.log ("2 Sekunden");
	count.textContent = "2";
	 delay (3);
	console.log ("5 Sekunden");
	count.textContent = "5";
}
button.addEventListener ("click", () => {
	countToFive ();
})
async / await
const delay = seconds => {
	return new Promise (
		resolve => setTimeout (resolve, seconds * 1000)
	)
};

const countToFive = async () => {
	console.log ("0 Sekunden");
	count.textContent = "0";
	await delay (1);
	console.log ("1 Sekunde");
	count.textContent = "1";
	await delay (1);
	console.log ("2 Sekunden");
	count.textContent = "2";
	await delay (3);
	console.log ("5 Sekunden");
	count.textContent = "5";
}
button.addEventListener ("click", () => {
	countToFive ();
})

Das zweite Script mit den Aufrufen von async und await ist genauso linear geschrieben wie die erste Fassung. Der Unterschied liegt in await. Statt mit der nächsten Zeile fortzufahren, wartet das Script mit await auf die Ausführung des Requests und führt erst dann die nächste Anweisung aus.

Asynchron mit fetch

fetch ist wie setTimeout von Haus aus asynchron.

const response = fetch ("https://api.com/values");
const json = response.json();
console.log (json);

Das funktioniert naturgemäß genauso wenig, weil jede Anfrage über das Netz Zeit braucht, ganz gleich, ob sie auf eine externe Ressource oder selbst auf den gleichen Webspace zugreift.

Also nutzen wir then.

fetch ("https://api.com/values")
	.then (response => response.json())
	.then (json => console.log (json));

Das funktioniert, liest sich aber nicht so intuitiv wie die erste Fassung. Dafür steht heute in den modernen Browser await / async zur Verfügung. async / await ist besser lesbar und nachvollziehbar als Script-Code mit Promisses. Dabei erzeugen async und await unter dem Zuckergruß Promisses.

async als Teil der Deklaration einer Funktion gibt an, dass der Code asynchron ausgeführt werden soll. await vor einer Anweisung gibt ein Promise zurück, dass die Funktion anhält und auf das Ergebnis wartet, bevor die Ausführung fortgesetzt wird.

const response = await fetch ("https://api.com/values");
const json = await response.json();
console.log (json);

await vor dem fetch führt dazu, dass der fetch-Request ausgeführt wird, bevor die nächste Zeile inAngriff genommen wird.

Ein etwas allgemeinerer Ansatz mit try – catch:

{ "list" : [
	{ "titel": "Eine kurze Geschichte von fast allem", "autor": "Bryson, Bill", "jahr": "2003" },
	{ "titel": "Accidental Empires", "autor": "Cringely, Robert X.", "jahr": "1992" },
	{ "titel": "Arm und Reich", "autor": "Diamond, Jared", "jahr": "1997" },
	{ "titel": "Bezaubernder April", "autor": "Elisabeth v. Armin", "jahr": "1992" }	
	]
}
const getBooks = async (num) => {
	try {
		let response = await fetch ("file.json");
		let json = await response.json ();
		let list = json.list;
		console.log (list[num].autor)
	} catch (e) {
		console.log ("Daten wurde nicht geladen", e);
	}
}

getBooks (2);

Asynchrone anonyme Funktionen

Davon können wir eine anonyme Funktion machen, die sofort dank der Schlüsselwörter async und await ohne den Aufruf getBooks (2) ausgeführt wird.

(async (num) => {
	try {
		let response = await fetch ("file.json");
		let json = await response.json ();
		let list = json.list;
		console.log (list[num].autor)
	} catch (e) {
		console.log ("Daten wurde nicht geladen", e);
	}
})(2);

Würden wir jetzt die Keywords async und await aus dem Script löschen, gäbe es eine Fehlermeldung in der Console.

Daten wurde nicht geladen
TypeError: response.json is not a function. (In 'response.json ()', 'response.json ' is undefined)
(anonyme Funktion)

response.json würde aufgerufen, bevor die Datei geladen wurde.