Читать книгу Angular - Manfred Steyer - Страница 51
Promises
ОглавлениеPromises sind Datenstrukturen, die mittlerweile Teil des ECMAScript-Standards sind. Sie repräsentieren Werte, die in der Regel asynchron ermittelt werden und bereits vorliegen können, aber nicht vorliegen müssen.
Der Aufrufer registriert bei einem Promise einen oder zwei Callbacks. Der eine nimmt das Ergebnis entgegen, sobald es vorliegt. Den anderen stößt der Promise im Fehlerfall an.
Um das zu veranschaulichen, erzeugt die nachfolgende Funktion einen Promise, der die oben verwendete Funktion setTimeout kapselt:
function timeout(time: number): Promise<number> {
return new Promise((resolve, reject) => {
if (time < 0) {
// Send error!
reject(`Don't be that negative!`);
return;
}
setTimeout(() => {
resolve(time);
}, time);
});
}
Da es sich hier um einen Promise<number> handelt, kann der Aufrufer davon ausgehen, dass es sich beim gelieferten Wert um eine number handelt.
Der instanziierte Promise bekommt zwei Funktionen übergeben: Die erste erhält in der Regel den Namen resolve, die zweite normalerweise reject. Sobald die asynchrone Operation erfolgreich ausgeführt wurde, ist resolve aufzurufen und dabei das Ergebnis zu übergeben. Im Fehlerfall kommt reject zur Ausführung. Diese Funktion nimmt eine Fehlermeldung entgegen.
Unsere Hilfsmethode timeout lässt sich nun wie folgt aufrufen:
timeout(1000)
.then(result => console.debug('Timeout!', result))
.catch(error => console.debug('error', error));
Der mit then registrierte Callback nennt sich Fulfillment-Handler. Er erhält das ermittelte Ergebnis, sobald es vorliegt. Der mit catch registrierte Callback ist der sogenannte Rejection-Handler. Der Promise bringt ihn im Fehlerfall zur Ausführung.
Dieser Aufruf sieht nicht viel anders aus als der im letzten Abschnitt. Tatsächlich entfalten Promises erst dann ihr Potenzial, wenn der Aufrufer sie verkettet:
timeout(1000)
.then(() => {
console.debug('Phase 1!', result);
return timeout(1000);
})
.then(() => {
console.debug('Phase 2!', result);
return timeout(1000);
})
.then(() => {
console.debug('Phase 3!', result);
return timeout(1000);
})
.then(() => {
console.debug('Phase 4!', result);
return timeout(1000);
})
.catch(error => console.error('error', error));
Liefert ein Handler einen weiteren Promise, erhält der nächste Fulfillment-Handler das Ergebnis, sobald es vorliegt. Im Fehlerfall ruft der Promise den nächsten Rejection-Handler auf.
Das ist bereits eine erste Verbesserung gegenüber der weiter oben gezeigten Pyramide of Doom. Es geht aber noch ein wenig besser, wie der nächste Abschnitt zeigt.