Promises

Modul #F4 - JavaScript - Promises.

Ziele

  • Du weisst, was Promises sind und wozu sie verwendet werden.
  • Du kannst, Promises korrekt anwenden in Funktionen.

Promises

Ein Promise repräsentiert einen Wert (oder ein Versprechen), der möglicherweise in der Zukunft verfügbar sein wird.

Promises werden oft verwendet, um asynchrone Operationen wie das Laden von Daten von einem Server oder das Ausführen eines HTTP-Requests zu verwalten. Ein Promise kann sich in einem von drei Zuständen befinden:

  • Pending (ausstehend): Der Promise ist noch nicht erfüllt (resolved) oder abgelehnt (rejected) worden.
  • Fulfilled (erfüllt): Die asynchrone Operation wurde erfolgreich abgeschlossen (resolved) und der Promise enthält den zurückgegebenen Wert.
  • Rejected (abgelehnt): Die asynchrone Operation ist fehlgeschlagen und der Promise enthält den Fehler.

Ein Promise kann mit der Funktion new Promise() erstellt werden. Diese Funktion nimmt eine Funktion als Argument, die zwei Parameter enthält: resolve und reject. resolve wird aufgerufen, wenn die Operation erfolgreich abgeschlossen wurde, und reject, wenn ein Fehler aufgetreten ist.

1
2
3
4
5
6
7
const promise = new Promise((resolve, reject) => {
    if (success) {
        resolve('success');
    } else {
        reject('error');
    }
});

Promises bieten zwei Methoden an, um mit dem Ergebnis oder dem Fehler der asynchronen Operation umzugehen:

  • then()
  • catch()

Die then() Methode wird verwendet, um eine Funktion zu registrieren, die ausgeführt wird, wenn das Promise erfolgreich erfüllt wird. Diese Funktion erhält das Ergebnis des erfüllten Promise als Parameter:

1
2
3
4
5
const promise = new Promise((resolve, reject) => resolve('success'));

promise.then((result) => {
    console.log(result) // 'success'
})

then() kann jedoch mehrmals hintereinander verwendet werden, um eine Kette von Funktionen zu erstellen, die nacheinander ausgeführt werden, wenn das Promise erfüllt wird.

Durch die Verwendung von then() in Kombination mit return in jeder Funktion kann eine Kette von Funktionen erstellt werden, die nacheinander ausgeführt werden, wobei jedes Ergebnis das Argument für die nächste Funktion in der Kette ist.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const promise = new Promise((resolve, reject) => resolve(2));

promise
    .then((result) => {
        console.log(result); // 2
        return result * 2;
    })
    .then((result) => {
        console.log(result); // 4
        return result * 2;
    })
    .then((result) => {
        console.log(result); // 8
    });

Die catch() Methode wird verwendet, um eine Funktion zu registrieren, die ausgeführt wird, wenn das Promise fehlschlägt. Diese Funktion erhält den Fehler als Parameter.

1
2
3
4
5
const promise = new Promise((resolve, reject) => reject('error'));

promise.catch((result) => {
    console.log(result); // 'error'
});

then() und catch() werden fast immer zusammen verwendet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const number = 10;
const promise = new Promise((resolve, reject) => {
    if (number > 0) {
        resolve('success');
    } else {
        reject('error');
    }
});

promise.then((result) => {
    console.log(result); // 'success'
}).catch((error) => {
    console.error(error); // 'error'
});

Promises als Function

Promises in Funktionen zu packen ist eine gängige Praxis in JavaScript, um asynchrone Operationen und Callbacks zu verwalten. Indem man Promises in Funktionen einbettet, kann man sicherstellen, dass die asynchronen Operationen sequentiell ausgeführt werden und man eine klare Struktur im Code hat.

Dazu muss man das gesamte Promise in der function returned:

1
2
3
4
5
6
7
8
9
function promiseFunction(number) {
    return new Promise((resolve, reject) => {
        if (number > 0) {
            resolve('success');
        } else {
            reject('error');
        }
    });
}

Nun kann man diese Funktion innerhalb von anderen Funktionen verwenden. Wichtig ist das diese mit await verwendet werden, um auf das Ergebnis des Promises zu warten, bevor der Rest der Funktion fortgesetzt wird. So kann man sicher gehen das man das Resultat aus dem Promise zur Verfügung hat und es danach in der Funktion verwenden kann. Wenn man jedoch ein await in einer Funktion verwendet muss die gesamte Funktion asynchron sein, dazu muss man vor die Funktion das Schlüsselwort asyncschreiben.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
function promiseFunction(number) {
    return new Promise((resolve, reject) => {
        if (number > 0) {
            resolve('success');
        } else {
            reject('error');
        }
    });
}

async function callPromiseFunction() {
    const successResult = await promiseFunction(10);
    console.log(successResult);

    const errorResult = await promiseFunction(-5);
    console.log(errorResult);
}

callPromiseFunction();
// 'success'
// Promise {<rejected>: 'error'}

Wenn man es nicht verwenden würde, würde der Code in der Funktion weiterfahren ohne das er evtl. das Resultat aus der Promise hat (das Promise hat noch den Zustand Pending).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function promiseFunction(number) {
    return new Promise((resolve, reject) => {
        if (number > 0) {
            resolve('success');
        } else {
            reject('error');
        }
    });
}

function callPromiseFunction() {
    const promise = promiseFunction(10).then((result) => {
        console.log(result);
    }).catch((error) => {
        console.error(error);
    })
    
    console.log(promise);
}

callPromiseFunction();
// Promise {<pending>}
// 'success'
Last modified October 25, 2023: fix feedbacks for F4 (6d840922)