# Promises

Een Promise is een ingebouwd Javascript object dat toelaat om asynchrone operaties af te handelen. Het is een alternatief voor callback functies. Promises bieden heel wat voordelen:

  • Maakt de asynchrone code leesbaarder.
  • Betere afhandeling van asynchrone operaties.
  • Beter controle over de flow, asynchrone operaties kunnen in serie of parallel uitgevoerd worden.
  • Eenvoudige afhandeling van fouten.

# Staat van een Promise

Een Promise kan zich in een van drie toestanden bevinden:

  • Pending: De initiële toestand wanneer de operatie nog niet is voltooid.
  • Fulfilled (In orde): De operatie is met succes voltooid.
  • Rejected (Afgewezen): De operatie is mislukt.

Analogie

Jouw vader belooft jou dat je volgende week een nieuwe smartphone krijgt. Je weet niet met zekerheid dat je deze smartphone krijgt. Enkel wanneer je in die tussenperiode braaf bent geweest bestaat de kans dat je deze krijgt. Ben je braaf geweest dan krijg je de smartphone van jouw tevreden vader. Is jouw vader niet tevreden, dan krijg je uiteraard deze smartphone niet.

Dat is een promise (Nl. belofte) en bevat 3 statussen, namelijk:

  • Pending: Je weet niet dat je de smartphone krijgt.
  • Fulfilled of resolved: Jouw vader is tevreden en koopt voor jou een smartphone.
  • Rejected: Jouw vader is niet tevreden en koopt geen smartphone.

# Promise aanmaken

Een Promise wordt gemaakt met de Promise-constructor, die een callback-functie accepteert. Deze callback-functie heeft standaard twee parameters, resolve en reject, die worden aangeroepen om de Promise te vervullen of af te wijzen.

  • Als alles goed is gegaan, dan roepen we de resolve() functie aan.
    • In deze functie geven we meestal als argument data mee om daarmee verder aan de slag te gaan. resolve(data)
  • Is er iets misgegaan, dan roepen we de reject() functie aan.
    • In deze functie geven we meestal als argument de fout mee. reject(error)
const myPromise = new Promise((resolve, reject) => {
  // Asynchrone operatie
  if (operatieIsSuccesvol) {
    resolve("Succesvolle uitkomst");
  } else {
    reject("Fout tijdens de operatie");
  }
});
1
2
3
4
5
6
7
8

Willen we een promise in een functie plaatsen, dan is het een goed idee om een promise te returnen.

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { name: "John", age: 30 };
      resolve(data); // Gegevens zijn met succes opgehaald
      // Of om afwijzing te simuleren: reject('Fout bij ophalen van gegevens');
    }, 2000);
  });
}
1
2
3
4
5
6
7
8
9

Analogie

const isDadHappy = false;

const willIGetNewSmartphone = new Promise((resolve, reject) => {
  if (isDadHappy) {
    resolve({
      brand: "Xiaomi",
      color: "Gradient Blue to Green",
    });
  } else {
    reject(new Error("Dad is not happy"));
  }
});
1
2
3
4
5
6
7
8
9
10
11
12

# Promise gebruiken

De methoden .then(), .catch() en finally() worden gebruikt om te reageren op de uitkomst van een Promise.

  • .then() wordt uitgevoerd wanneer de Promise is vervuld. (resolve(data) geeft data door aan then((data) => {}))
  • .catch() wordt uitgevoerd bij afwijzing.(reject(error) geeft data door aan catch((error) => {}))
  • finally() wordt sowieso uitgevoerd ongeacht of een belofte is vervuld of verworpen.
myPromise
  .then((result) => {
    console.log("Vervuld:", result);
  })
  .catch((error) => {
    console.error("Afgewezen:", error);
  })
  .finally(() => {
    console.log("Promise is voorbij.");
  });
1
2
3
4
5
6
7
8
9
10
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { name: "John", age: 30 };
      resolve(data); // Gegevens zijn met succes opgehaald
      // Of om afwijzing te simuleren: reject('Fout bij ophalen van gegevens');
    }, 2000);
  });
}

// Gebruik van de Promise
fetchData()
  .then((data) => {
    console.log("Gegevens opgehaald:", data);
  })
  .catch((error) => {
    console.error("Fout bij ophalen van gegevens:", error);
  });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Promises

Voorbeeld

function createApp() {
  // ...
}

promise
  .then((success) => {
    console.log(success);
    createApp();
  })
  .catch((reason) => {
    console.log(reason);
    createApp();
  });
1
2
3
4
5
6
7
8
9
10
11
12
13
promise
  .then((success) => console.log(success))
  .catch((reason) => console.log(reason))
  .finally(() => createApp()); // Korter met finally!
1
2
3
4

Analogie

willIGetNewSmartphone
  .then((data) => console.log(data))
  .catch((error) => console.error(error));
1
2
3

Promises of Async/Await?

Promises zijn ontzettend handig en een leesbare methode om asynchroon te programmeren.

Async/Await is een alternatieve syntax om asynchrone functies op te roepen. Async/Await werd later toegevoegd aan Javascript omdat de syntax meer vertrouwd aanvoelt. Maar Promises zullen sowieso nog gebruikt worden bij het aanmaken van asynchrone functies.

Beide methodes zijn goed en het is de keuze van de developer welke techniek hij zal hanteren.

# Chaining van promises

Promises kunnen worden geketend met meerdere .then()-calls, wat bekend staat als “Promise chaining”. Dit helpt bij het sequentieel uitvoeren van asynchrone taken en zal een alternatief bieden voor de callback-hell.

asyncFunctionThatIsAPromise()
  .then((result) => {
    return anotherAsyncFunction(result);
  })
  .then((finalResult) => {
    console.log("Laatste resultaat:", finalResult);
  })
  .catch((error) => {
    console.error("Fout tijdens de keten:", error);
  });
1
2
3
4
5
6
7
8
9
10
function getUserDetails(userId) {
  return new Promise((resolve, reject) => {
    // Simulatie van het ophalen van gebruikersgegevens
    setTimeout(() => {
      const user = { id: userId, name: "Alice" };
      resolve(user);
    }, 2000);
  });
}

function getUserPosts(user) {
  return new Promise((resolve, reject) => {
    // Simulatie van het ophalen van gebruikersposts
    setTimeout(() => {
      const posts = ["Post 1", "Post 2"];
      resolve({ user, posts });
    }, 2000);
  });
}

// Chaining van Promises
getUserDetails(123)
  .then((user) => getUserPosts(user))
  .then((result) => {
    console.log("Gebruikersgegevens en posts:", result);
  })
  .catch((error) => {
    console.error("Fout bij ophalen van gegevens:", error);
  });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

Goed

doSomething()
  .then((result) => doSomethingElse(result))
  .then((newResult) => doThirdThing(newResult))
  .then((finalResult) => {
    console.log(`Got the final result: ${finalResult}`);
  })
  .catch(failureCallback);
1
2
3
4
5
6
7

Callback Hell

doSomething((result) => {
  doSomethingElse(
    result,
    (newResult) => {
      doThirdThing(
        newResult,
        (finalResult) => {
          console.log("Got the final result: " + finalResult);
        },
        failureCallback
      );
    },
    failureCallback
  );
}, failureCallback);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Analogie

Jouw kind belooft aan zijn beste vriend om zijn smartphone te tonen wanneer jouw vader een heeft gekocht. Dat is een bijkomende belofte of promise in het verhaal. Deze tweede belofte is pas van kracht als de eerste belofte vervuld is.

const showOff = function (phone) {
  return new Promise((resolve, reject) => {
    const message = `Hey friend, I have a new ${phone.color} ${phone.brand} phone.`;
    resolve(message);
  });
};
1
2
3
4
5
6

Laten we beide beloftes aan elkaar vebinden. Jouw kind kan pas de tweede belofte showOff starten nadat de willIGetNewSmartphone belofte vervuld is.

willIGetNewSmartphone
  .then((phone) => showOff(phone))
  .then((message) => console.log(message))
  .catch((error) => console.error(error));
1
2
3
4

Volledig voorbeeld

const willIGetNewSmartphone = (isDadHappy) => {
  return new Promise((resolve, reject) => {
    if (isDadHappy) {
      resolve({
        brand: "Xiaomi",
        color: "Gradient Blue to Green",
      });
    } else {
      reject(new Error("Dad is not happy"));
    }
  });
};

const showOff = (phone) => {
  return new Promise((resolve, reject) => {
    const message = `Hey friend, I have a new ${phone.color} ${phone.brand} phone.`;
    resolve(message);
  });
};

function askDadForSmartphone(isDadHappy) {
  willIGetNewSmartphone(isDadHappy)
    .then((phone) => showOff(phone))
    .then((message) => console.log(message))
    .catch((error) => console.error(error));
}

askDadForSmartphone(true);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# Parallel uitvoeren van promises

  • Promise.all(): Wacht totdat alle Promises in een iterable zijn vervuld of er een wordt afgewezen.
  • Promise.race(): Wacht op de eerste Promise in een iterable die vervuld of afgewezen wordt.

# Promise.all()

Met Promise.all() kunnen we wachten tot alle Promises in een iterable zijn vervuld of er een wordt afgewezen.

const promise1 = asyncFunction1();
const promise2 = asyncFunction2();

Promise.all([promise1, promise2])
  .then(([result1, result2]) => {
    console.log("Alle promises zijn vervuld:", result1, result2);
  })
  .catch((error) => {
    console.error("Ten minste één promise is afgewezen:", error);
  });
1
2
3
4
5
6
7
8
9
10
const promise1 = fetchData("URL1");
const promise2 = fetchData("URL2");

Promise.all([promise1, promise2])
  .then((results) => {
    console.log("Alle data is opgehaald:", results);
  })
  .catch((error) => {
    console.error("Fout bij ophalen van data:", error);
  });
1
2
3
4
5
6
7
8
9
10
const a = () => new Promise((resolve) => setTimeout(() => resolve("a"), 2000));
const b = () => new Promise((resolve) => setTimeout(() => resolve("b"), 1000));
const c = () => new Promise((resolve) => setTimeout(() => resolve("c"), 1000));
const d = () => new Promise((resolve) => setTimeout(() => resolve("d"), 1000));

console.time("promise.all");
Promise.all([a(), b(), c(), d()])
  .then((results) => console.log(`Done! ${results}`))
  .catch(console.error)
  .finally(() => console.timeEnd("promise.all"));
1
2
3
4
5
6
7
8
9
10

# Promise.race()

Met Promise.race() wachten we op de eerste Promise in een iterable die vervuld of afgewezen wordt.

const promise1 = fetchData("URL1");
const promise2 = fetchData("URL2");

Promise.race([promise1, promise2])
  .then((winner) => {
    console.log("De eerste die klaar is:", winner);
  })
  .catch((error) => {
    console.error("Fout bij ophalen van data:", error);
  });
1
2
3
4
5
6
7
8
9
10
const a = () => new Promise((resolve) => setTimeout(() => resolve("a"), 2000));
const b = () => new Promise((resolve) => setTimeout(() => resolve("b"), 1000));
const c = () => new Promise((resolve) => setTimeout(() => resolve("c"), 1000));
const d = () => new Promise((resolve) => setTimeout(() => resolve("d"), 1000));

console.time("promise.race");
Promise.race([a(), b(), c(), d()])
  .then((results) => console.log(`Done! ${results}`))
  .catch(console.error)
  .finally(() => console.timeEnd("promise.race"));
1
2
3
4
5
6
7
8
9
10
© 2025 Arteveldehogeschool Laatst bijgewerkt: 13/1/2025, 10:02:14