Javascript Promises erleichtern die Programmierung von Funktionen zur Behandlung von asynchronen Ereignissen.
Traditionell wurden einer Funktion Referenzen auf Callback-Funktionen mitgegeben, die nach Erfüllung oder Abbruch aufzurufen sind. Der Aufruf dieser Callbacks musste dann explizit in der Funktion programmiert werden:
function successCallback(result){
console.log( 'Success: ' + result );
}
function failureCallback(error){
console.log( 'Failure: ' + error );
}
function myFunction(arguments, successCallback, failureCallback) {
# ... async code ...
if (success && typeof successCallback === 'function') {
successCallback('my result');
}
}
myFunction((arguments, successCallback, failureCallback);
Mit dem Einsatz eines Promise kann man diese Funktion und den Aufruf vereinfachen und standardisieren:
function myFunction(arguments) {
return new Promise((resolve, reject)=>{
# ... async code ...
if (success) {
resolve('my result');
}
});
}
myFunction(arguments).then(successCallback, failureCallback)
Die Funktion myFunction
gibt ein Promise
Objekt zurück, an das die Behandlungsroutinen für erfolgreiche Abarbeitung (resolve
) und/oder Abbruch (reject
) übergeben werden. Dieses Objekt bleibt im Status „pending”, bis es nach Abarbeitung des asynchronen Codes mit resolve
() oder reject
() beendet und automatisch die entsprechenden Behandlungsroutinen aufgerufen werden.
Verkettung
Sind asynchrone Operationen voneinander abhängig, so dass die nächste Funktion erst starten kann wenn die vorherige erledigt ist, kann man Promises
auch einfach verketten. Das ist dadurch möglich, dass die .then()
Funktion auch wieder ein Promise
Objekt zurückgibt:
const promise = doSomething();
const promise2 = promise.then(successCallback, failureCallback);
Das zweite Promise
Objekt (promise2
) repräsentiert jetzt nicht nur die Abarbeitung der Funktion doSomething()
, sondern auch die übergebenen Behandlungsroutinen. Das können aber auch wieder asynchrone Funktionen sein, die ein Promise
Objekt zurückgeben. Ist das der Fall, werden diese Funktionen in einer Kette abgearbeitet, wobei die folgende Funktion immer auf die Beendigung (also den Aufruf der resolve
bzw. reject
Funktion) der vorhergehenden wartet.
function doSomething() {
return new Promise((resolve) => {
console.log("doing something...";
setTimeout(() => {
console.log("Did something");
resolve("my result");
}, 200);
});
}
doSomething()
.then((result) => doSomethingElse(result))
.then((newResult) => doThirdThing(newResult))
.then((finalResult) => {
console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
Die .catch Funktion catch(failureCallback)
ist ein Alias für then(null, failureCallback)
. Wenn Die Fehlerbehandlungsroutine für alle Funktionen die Gleiche ist, kann sie mit catch
ans Ende der Kette gehängt werden und gilt dann für alle Funktionen gleichermaßen.
Es ist wichtig, dass die mit .then()
übergebenen Funktionen immer ein Promise
Objekt zurückgeben. Ansonsten bleibt das Promise der vorhergehenden Funktion ungelöst (floating).
Die gleiche Funktion wie die Kette von .then()
Funktionen erfüllt übrigens eine Reihe von await
Anweisungen in eine async
Funktion, was möglicherweise übersichtlicher ist.
async function doIt(){
try {
const result_1 = await doSomething();
const result_2 = await doSomethingElse(result_1);
const finalResult = await doThirdThing(Result_2);
console.log(`Got the final result: ${finalResult}`);
} catch (error) {
failureCallback(error);
}
}
doIt();
Kombinationen
Promises
können miteinander kombiniert werden, so dass eine Folgefunktion erst ausgeführt wird, wenn das Kombinationsziel erfüllt ist. Die Funktionen im Promise
laufen dabei parallel ab und warten nicht aufeinander. Es existieren vier unterschiedliche Varianten für die Startbedingung der .then
Funktion:
Promise.all((func2, func2, ...).then((result1, result2, result3)=>{ ... use results ... }
Die.then
Funktion Wird ausgeführt, wenn allePromises
entwederresolved
sind oder einrejected
auftritt. Der erstereject
bricht alle anderen Funktionen ab.Promis.allSettled
Wie oben, aber wird nicht beim erstenreject
abgebrochen, sondern erst ausgeführt, wenn alle Funktionen entwederresolved
oderrejected
sind.Promise.any
Wie oben, aber diePromise
wird erfüllt, wenn die erste der angegebenen Funktionenresolve
aufruft oder wenn alle Funktionenrejected
sind. Der Ergebniswert ist entweder das Ergebnis der ersten erfolgreichen Funktion oder ein Array der reject-Ergebnisse.Promise.race(promise1, promise2, ...).then((result)=>{ ... use results ... }
Gibt einPromise
Objekt zurück, das erfüllt wird, wenn eines der übergebenenPromises
erfüllt (resolve
) oder abgebrochen (reject
) wird; das Ergebnis ist das des ersten beendetenPromise
.
Quellen: