Domů O mně Služby Portfolio Učím Blog Kontakt
← Zpět na učím

07.04 Promises úvod

Výuka

Co je Promise?

Promise (příslib, slib) je objekt reprezentující budoucí hodnotu - něco, co možná ještě není dostupné, ale bude (nebo nastane chyba).

Představ si to jako:

Jdeš do fastfoodu a objednáš si burger. Zaplatíš 100 Kč. Burger není hned připravený, takže ti dají stvrzenku s číslem objednávky.

🧾 Stvrzenka = Promise
Číslo objednávky: #42
Představuje: budoucí burger
Status: čeká se na přípravu

Co stvrzenka znamená:

  • Budeš mít burger (eventually)
  • Zatím ho nemáš, ale máš záruku, že přijde
  • 📱 Můžeš dělat jiné věci (volat kamarádovi, sednout si) - nečekáš u pultu!
  • 🔔 Dostaneš upozornění, až bude hotovo

Dva možné výsledky:

  1. Fulfilled (splněno) - dostaneš burger
  2. Rejected (odmítnuto) - "Omlouváme se, burgery došly"

Proč Promises?

Callbacks měly 2 velké problémy:

1. Inversion of Control (Ztráta kontroly)

S callbacky předáváš kontrolu někomu jinému:

// Předáváš svůj callback třetí straně
analytics.trackPurchase(data, function myCallback() {
  chargeCreditCard(); // Důvěřuješ, že to zavolá JEDNOU!
});

Problém: Nevíš, jestli třetí strana:

  • Zavolá callback 1x, 5x, nebo 0x
  • Zavolá ho včas
  • Předá správné parametry

Promise řešení: Místo předání callbacku dostaneš objekt (Promise), který kontroluješ TY:

// Dostáváš Promise - kontroluješ ho TY!
const promise = analytics.trackPurchase(data);

promise.then(() => {
  chargeCreditCard(); // TY rozhoduješ, co se stane
});

2. Callback Hell (Pyramid of Doom)

Vnořené callbacky = nečitelný kód.

Promise řešení: Lineární řetězení:

// ❌ Callback hell
step1((result1) => {
  step2(result1, (result2) => {
    step3(result2, (result3) => {
      done(result3);
    });
  });
});

// ✅ Promises - lineární!
step1()
  .then(result1 => step2(result1))
  .then(result2 => step3(result2))
  .then(result3 => done(result3));

Jak Promise funguje?

Promise je stavový automat - může být v jednom ze 3 stavů:

┌──────────────┐
   PENDING      Čeká se (výchozí stav)
 (čekající)   
└──────┬───────┘
       
       
  ┌────┴────┐
           
           
┌─────────┐ ┌─────────┐
│FULFILLED│ │REJECTED 
(splněno) (odmítnuté)
└─────────┘ └─────────┘

Pravidla:

  1. Pending → může přejít na Fulfilled nebo Rejected
  2. FulfilledFINÁLNÍ stav (už se nemění)
  3. RejectedFINÁLNÍ stav (už se nemění)
  4. 🔒 Immutable - jakmile je promise vyřešena, nemůže se změnit

Metafora s burgerem:

  • Pending: Burger se vaří
  • Fulfilled: Máš burger v ruce ✅
  • Rejected: "Burgery došly" ❌
  • Immutable: Už to nemůžeš změnit - buď máš burger, nebo ne

Klíčové koncepty

  • Future Value (budoucí hodnota) - Promise reprezentuje hodnotu, která přijde později
  • Time-independent (nezávislý na čase) - Promise funguje stejně, ať hodnota přijde hned nebo za hodinu
  • Immutable (neměnný) - Vyřešený promise se už nemění
  • Chainable (řetězitelný) - Můžeš řetězit .then() za sebou

JavaScript

Vytvoření Promise

// Promise.resolve - vytvoř okamžitě vyřešený promise
const promise = Promise.resolve(42);

promise.then((value) => {
  console.log(value);  // 42
});

// Promise constructor - pro async operace
const asyncPromise = new Promise((resolve, reject) => {
  // Simulace async operace
  setTimeout(() => {
    resolve('Hotovo po 1 sekundě');
  }, 1000);
});

asyncPromise.then((result) => {
  console.log(result);  // "Hotovo po 1 sekundě" (po 1s)
});

Co se stalo?

  1. Promise.resolve(42) vytvoří okamžitě vyřešený promise s hodnotou 42
  2. .then() zaregistruje callback, který se zavolá s hodnotou
  3. Promise constructor dostane funkci (resolve, reject) => {}
  4. Když zavoláš resolve(value), promise přejde do stavu Fulfilled

Promise constructor - podrobně

new Promise((resolve, reject) => {
  // Tady je tvůj async kód

  // Úspěch → zavolej resolve
  if (/* vše OK */) {
    resolve(value);  // Promise → Fulfilled s hodnotou
  }

  // Chyba → zavolej reject
  if (/* chyba */) {
    reject(error);  // Promise → Rejected s chybou
  }
});

Praktický příklad - obalení callback API do Promise

// Callback-based API (Node.js)
function readFileCallback(filename, callback) {
  setTimeout(() => {
    if (filename.endsWith('.txt')) {
      callback(null, 'Obsah souboru');
    } else {
      callback(new Error('Neplatný soubor'));
    }
  }, 1000);
}

// Promise wrapper
function readFilePromise(filename) {
  return new Promise((resolve, reject) => {
    readFileCallback(filename, (err, data) => {
      if (err) {
        reject(err);  // Chyba → rejected
      } else {
        resolve(data);  // Úspěch → fulfilled
      }
    });
  });
}

// Použití
readFilePromise('data.txt').then((data) => {
  console.log('Data:', data);
});

// Výstup (po 1s):
// Data: Obsah souboru

Future Value - příklad s cheeseburgerem

// Funkce vrací Promise (stvrzenku)
function orderCheeseburger() {
  return new Promise((resolve, reject) => {
    console.log('Připravuji burger...');

    setTimeout(() => {
      const burgersAvailable = true;

      if (burgersAvailable) {
        resolve('🍔 Váš burger');  // Fulfilled
      } else {
        reject('❌ Burgery došly');  // Rejected
      }
    }, 2000);
  });
}

// Dostaneš Promise (stvrzenku)
const receipt = orderCheeseburger();

console.log('Mám stvrzenku, zatím dělám jiné věci...');

// Až bude hotovo, dostaneš upozornění
receipt.then((burger) => {
  console.log('Mám burger!', burger);
});

// Výstup:
// Připravuji burger...
// Mám stvrzenku, zatím dělám jiné věci...
// (po 2s): Mám burger! 🍔 Váš burger

Co se stalo?

  1. orderCheeseburger() vrátí Promise (stvrzenku) - OKAMŽITĚ
  2. Program pokračuje dál (neblokuje se)
  3. Po 2 sekundách se Promise vyřeší → zavolá se .then() callback

Promise je immutable

const promise = Promise.resolve(42);

promise.then(value => console.log('První:', value));
promise.then(value => console.log('Druhý:', value));
promise.then(value => console.log('Třetí:', value));

// Výstup:
// První: 42
// Druhý: 42
// Třetí: 42

// Promise se NEVYČERPÁ! Můžeš ho použít vícekrát.

TypeScript

TypeScript přidává generické typy pro Promise: Promise

Typované Promises

// Promise<number> - promise s číselnou hodnotou
const numberPromise: Promise<number> = Promise.resolve(42);

numberPromise.then((value: number) => {
  console.log(value.toFixed(2));  // ✅ TS ví, že je to number
});

// Promise<string>
const stringPromise: Promise<string> = Promise.resolve('Hello');

stringPromise.then((value: string) => {
  console.log(value.toUpperCase());  // ✅ TS ví, že je to string
});

// Promise<User>
interface User {
  id: number;
  name: string;
}

const userPromise: Promise<User> = new Promise((resolve) => {
  setTimeout(() => {
    resolve({ id: 1, name: 'Jan' });
  }, 1000);
});

userPromise.then((user: User) => {
  console.log(user.name);  // ✅ TS ví, že user má property name
});

Funkce vracející Promise

// Explicitní návratový typ: Promise<string>
function fetchData(): Promise<string> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data loaded');
    }, 1000);
  });
}

// TS automaticky odvodí Promise<number>
function calculate() {
  return Promise.resolve(42);  // Promise<number> (inference)
}

Promise constructor s typy

// Typy pro resolve a reject
const promise = new Promise<string>((resolve, reject) => {
  // resolve očekává string
  resolve('OK');  // ✅

  // resolve('OK'); - kdyby se to zakomentovalo
  // reject(new Error('Chyba'));  // ✅

  // resolve(123);  // ❌ Error - očekává string
});

Rozdíl JS vs TS

JavaScript:

  • Promise bez typů
  • Nevíš, co dostaneš v .then()
  • Chyby až za běhu

TypeScript:

  • Promise - víš přesně, jaký typ dostaneš
  • Autocomplete v .then() callbacku
  • Kontrola typů při compilaci
// JS - nevíš co dostaneš
fetchData().then((data) => {
  console.log(data.toUpperCase());  // Možná chyba (pokud není string)
});

// TS - víš přesně
fetchData().then((data: string) => {
  console.log(data.toUpperCase());  // ✅ TS ví, že je to string
  // console.log(data.toFixed());   // ❌ Error - string nemá toFixed
});

Tip

💡 Promise states diagram:

┌─────────────┐
   PENDING    (výchozí stav)
└──────┬──────┘
       
 ┌─────┴─────┐
            
            
FULFILLED  REJECTED
(success)  (error)

💡 Promise je jako účtenka:

// Dostaneš účtenku (Promise) OKAMŽITĚ
const receipt = orderFood();

// Můžeš dělat jiné věci
goToTable();
callFriend();

// Až jídlo dorazí, dostaneš upozornění
receipt.then(food => eat(food));

💡 Promises vs Callbacks - Future Value:

// ❌ Callback - "zavolej mě, až máš hodnotu"
fetchData((err, data) => {
  if (err) { /* ... */ }
  console.log(data);
});

// ✅ Promise - "dej mi účtenku, já počkám"
const promise = fetchData();
promise.then(data => console.log(data));

💡 Promise.resolve - zkratka:

// Dlouhá cesta
const promise = new Promise((resolve) => {
  resolve(42);
});

// Zkratka
const promise = Promise.resolve(42);

💡 Immutability = bezpečnost:

const promise = fetchData();

// Můžeš předat komukoliv - nikdo ho nemůže změnit!
module1.use(promise);
module2.use(promise);
// Oba dostanou stejnou hodnotu, nikdo ji nezmění

Kvíz

Které výroky o Promises jsou pravdivé?

- Promise je "účtenka" za budoucí hodnotu - může být dostupná hned nebo později

- 3 stavy: Pending (čeká), Fulfilled (úspěch), Rejected (chyba)

- Promise je immutable - jakmile je vyřešen, NIKDY se už nezmění!

- S callbacky ztrácíš kontrolu, Promise ti dává objekt, který kontroluješ TY

🎯 Závěrečný projekt

Po dokončení všech 8 dílů vytvoříte jednoduchou Todо aplikaci v čistém JavaScriptu. Naučíte se, jak aplikovat vše, co jste se naučili, na reálný projekt.

Zobrazit podrobnosti projektu →

Připraveni začít?

Zaregistrujte se a získejte přístup ke všem dílům tohoto seriálu

Kontaktujte mě

Informace o seriálu

Obtížnost

Délka

Cca 480 minut

Počet videí

8 videí + projekty

Certifikát

Po dokončení obdržíte certifikát


Lekce v této sekci


Struktura lekcí (souborový strom)

06. Typescript specifika
  • v přípravě
08. Moduly tridy
  • v přípravě
09. React zaklady
  • v přípravě
10. React hooks
  • v přípravě
12. Nextjs server
  • v přípravě
13. Databaze auth
  • v přípravě
14. Nextjs pokrocile
  • v přípravě