07.08 Async/Await
Výuka
Proč Async/Await?
Promises vyřešily callback hell, ale stále vypadají asynchronně:
// ❌ Promise chain - lepší než callbacks, ale stále async syntax
fetchUser()
.then(user => fetchSettings(user.id))
.then(settings => fetchArticles(settings.limit))
.then(articles => console.log(articles))
.catch(handleError);
Problém: Náš mozek přemýšlí synchronně (krok po kroku), ale kód vypadá asynchronně (.then() chains).
Co kdybychom mohli psát async kód, který VYPADÁ jako synchronní?
// ✅ Async/await - vypadá jako synchronní kód!
async function loadData() {
const user = await fetchUser();
const settings = await fetchSettings(user.id);
const articles = await fetchArticles(settings.limit);
console.log(articles);
}
Async/await je syntactic sugar (syntaktický cukr) nad Promises - pod kapotou jsou to stále Promises, ale syntax je mnohem čitelnější!
Představ si to jako:
Máš recept na vaření:
❌ S Promises (.then()):
1. Sežeň vajíčka.then(() => {
2. Rozklepni vajíčka.then(() => {
3. Vař vejce.then(() => {
4. Sněz vejce
})
})
})
✅ S Async/Await:
async function vařVejce() {
const vajíčka = await sežeňVajíčka();
const rozklepnutá = await rozklepniVajíčka(vajíčka);
const uvařená = await vařVejce(rozklepnutá);
snězVejce(uvařená);
}
Druhý způsob je přirozenější! Čte se shora dolů, jako běžný recept.
Co je async funkce?
async funkce je funkce, která:
- Vždy vrací Promise (i když uvnitř vrátíš hodnotu)
- Může používat
awaituvnitř
Syntaxe:
async function nazev() {
// Můžeš používat await
}
Pravidla:
asyncpředfunction→ funkce vrací Promise- Vrátíš-li hodnotu → zabalí se do
Promise.resolve(hodnota) - Vyhodíš-li chybu → zabalí se do
Promise.reject(chyba)
Příklad:
async function getNumber() {
return 42; // Vypadá jako return hodnoty
}
// Ale ve skutečnosti:
getNumber(); // → Promise.resolve(42)
// Použití:
getNumber().then(num => console.log(num)); // 42
Je to ekvivalentní s:
function getNumber() {
return Promise.resolve(42);
}
Co je await?
await = "počkej na vyřešení Promise"
Pravidla:
- Pouze v
asyncfunkcích (nemůžeš použít v top-level kódu nebo běžných funkcích) - Pozastaví vykonávání funkce, dokud Promise není vyřešen
- Vrací hodnotu z Promise (ne Promise samotný!)
Syntaxe:
const hodnota = await promise;
Co se stane:
1. await promise
↓
2. Funkce se POZASTAVÍ (pause)
↓
3. Čeká, až se promise vyřeší
↓
4. Pokračuje s hodnotou z promise
Příklad:
async function example() {
console.log('Start');
const result = await Promise.resolve(42);
// Program se tu ZASTAVÍ a čeká na Promise
console.log('Result:', result); // 42
console.log('End');
}
example();
console.log('After call');
// Výstup:
// Start
// After call
// Result: 42
// End
Co se stalo?
example()se spustila → vypsal "Start"- Narazila na
await→ pozastavila se - Vrátila se kontrola → vypsal se "After call"
- Promise se vyřešil →
example()pokračovala - Vypsal se "Result: 42" a "End"
Async/Await vs Promises
Stejný kód, dva způsoby zápisu:
S Promises:
function loadUserData(userId) {
return fetchUser(userId)
.then(user => {
return fetchPosts(user.id);
})
.then(posts => {
return fetchComments(posts[0].id);
})
.then(comments => {
return comments;
});
}
S Async/Await:
async function loadUserData(userId) {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
const comments = await fetchComments(posts[0].id);
return comments;
}
Výhody async/await:
- ✅ Čitelnější - vypadá jako synchronní kód
- ✅ Lineární - čte se shora dolů
- ✅ Méně syntaxe - žádné
.then() - ✅ Snadnější debugging - call stack je přehlednější
- ✅ Error handling s
try/catch(viz další lekce)
Sekvenční vs Paralelní běh
POZOR! await pozastaví funkci → kroky běží sekvenčně (jeden po druhém).
❌ Sekvenčně (POMALÉ):
async function loadData() {
const user = await fetchUser(); // Čeká 1s
const posts = await fetchPosts(); // Čeká dalších 1s
const comments = await fetchComments(); // Čeká dalších 1s
// Celkem: 3 sekundy!
}
✅ Paralelně (RYCHLÉ):
async function loadData() {
// Spusť všechny najednou
const userPromise = fetchUser();
const postsPromise = fetchPosts();
const commentsPromise = fetchComments();
// Počkej na všechny
const user = await userPromise;
const posts = await postsPromise;
const comments = await commentsPromise;
// Nebo lépe s Promise.all():
const [user2, posts2, comments2] = await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments()
]);
// Celkem: 1 sekunda (nejdelší)!
}
Return value z async funkce
Async funkce VŽDY vrací Promise!
async function getValue() {
return 42; // Vrátíš hodnotu
}
const result = getValue();
console.log(result); // Promise { <fulfilled>: 42 }
// Použij .then() nebo await:
getValue().then(value => console.log(value)); // 42
// Nebo:
const value = await getValue(); // 42 (v async funkci)
Error handling
Pokud Promise selže → await vyhodí chybu!
async function example() {
try {
const result = await Promise.reject('Chyba!');
console.log('Nikdy se nedostaneš sem');
} catch (error) {
console.error('Chytil jsem chybu:', error); // 'Chyba!'
}
}
(Detailní error handling bude v další lekci 7.9)
Klíčové koncepty
asyncfunkce - Vždy vrací Promise, může používatawaitawaitvýraz - Pozastaví funkci, dokud Promise není vyřešen, vrací hodnotu- Syntactic sugar - Pod kapotou jsou stále Promises
- Synchronní vzhled - Vypadá jako synchronní kód, ale je async
- Sekvenční await - Každý
awaitčeká → pomalé - Paralelní běh - Použij
Promise.all()pro paralelizaci
JavaScript
Základní async funkce
// Async funkce VŽDY vrací Promise
async function greet() {
return 'Hello!'; // Automaticky Promise.resolve('Hello!')
}
greet().then(msg => console.log(msg)); // 'Hello!'
// Ekvivalentní s:
function greet() {
return Promise.resolve('Hello!');
}
Použití await
async function fetchData() {
console.log('Začínám...');
// Simulace async operace
const data = await new Promise((resolve) => {
setTimeout(() => resolve('Data načtena'), 1000);
});
console.log(data); // 'Data načtena' (po 1s)
return data;
}
fetchData().then(result => {
console.log('Hotovo:', result);
});
// Výstup:
// Začínám...
// (po 1s): Data načtena
// Hotovo: Data načtena
Co se stalo?
fetchData()se spustila → "Začínám..."awaitpozastavil funkci na 1 sekundu- Promise se vyřešil → "Data načtena"
return data→ Promise.resolve('Data načtena').then()dostal hodnotu → "Hotovo: Data načtena"
Sekvenční async operace
async function loadUserData(userId) {
console.log('Loading user...');
const user = await fetch(`/api/users/${userId}`).then(r => r.json());
console.log('User loaded:', user.name);
console.log('Loading posts...');
const posts = await fetch(`/api/posts?userId=${userId}`).then(r => r.json());
console.log('Posts loaded:', posts.length);
console.log('Loading comments...');
const comments = await fetch(`/api/comments?postId=${posts[0].id}`).then(r => r.json());
console.log('Comments loaded:', comments.length);
return { user, posts, comments };
}
// Použití
loadUserData(1).then(data => {
console.log('All data:', data);
});
Paralelní běh s Promise.all()
async function loadAllData() {
console.log('Starting parallel fetch...');
// Spusť všechny najednou
const [users, posts, comments] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json()),
fetch('/api/comments').then(r => r.json())
]);
console.log('All loaded!');
return { users, posts, comments };
}
loadAllData().then(data => {
console.log('Users:', data.users.length);
console.log('Posts:', data.posts.length);
console.log('Comments:', data.comments.length);
});
Await v loop
// ❌ Sekvenčně - POMALÉ
async function processFilesSlow(files) {
const results = [];
for (const file of files) {
const content = await readFile(file); // Čeká na každý soubor!
results.push(content);
}
return results;
}
// ✅ Paralelně - RYCHLÉ
async function processFilesFast(files) {
const promises = files.map(file => readFile(file));
const results = await Promise.all(promises);
return results;
}
Async arrow funkce
// Async arrow function
const fetchData = async () => {
const data = await fetch('/api/data');
return data.json();
};
// Použití
fetchData().then(data => console.log(data));
// Async arrow v .map()
const userIds = [1, 2, 3];
Promise.all(
userIds.map(async (id) => {
const user = await fetch(`/api/users/${id}`);
return user.json();
})
).then(users => console.log(users));
Return Promise z async funkce
async function fetchUser(id) {
// Můžeš vrátit Promise přímo
return fetch(`/api/users/${id}`).then(r => r.json());
// Je to ekvivalentní s:
// const response = await fetch(`/api/users/${id}`);
// const data = await response.json();
// return data;
}
Async IIFE (Immediately Invoked Function Expression)
// Top-level await není podporován všude, použij async IIFE
(async () => {
const data = await fetchData();
console.log(data);
})();
// Nebo s error handling:
(async () => {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}
})();
Timeout s async/await
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function delayedGreeting() {
console.log('Hello');
await timeout(1000);
console.log('World'); // Po 1 sekundě
}
delayedGreeting();
// Výstup:
// Hello
// (po 1s): World
TypeScript
TypeScript přidává typovou bezpečnost pro async funkce a jejich návratové hodnoty.
Typované async funkce
// Explicitní návratový typ: Promise<string>
async function fetchMessage(): Promise<string> {
const response = await fetch('/api/message');
const data = await response.json();
return data.message; // TS ví, že musí být string
}
// TS automaticky odvodí Promise<number>
async function calculate() {
return 42; // TS odvodí: Promise<number>
}
Await s typovanými Promises
interface User {
id: number;
name: string;
email: string;
}
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);
const user: User = await response.json();
return user;
}
// Použití
async function main() {
const user = await fetchUser(1);
// TS ví, že user: User
console.log(user.name); // ✅ OK
// console.log(user.phone); // ❌ Error - User nemá phone
}
Generické async funkce
// Generická async funkce
async function fetchData<T>(url: string): Promise<T> {
const response = await fetch(url);
const data: T = await response.json();
return data;
}
// Použití
interface Post {
id: number;
title: string;
}
const post = await fetchData<Post>('/api/posts/1');
console.log(post.title); // TS ví, že je to string
Error handling s typy
class ApiError extends Error {
constructor(public statusCode: number, message: string) {
super(message);
}
}
async function fetchUserSafe(id: number): Promise<User> {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new ApiError(response.status, 'Failed to fetch user');
}
const user: User = await response.json();
return user;
} catch (error) {
if (error instanceof ApiError) {
console.error('API Error:', error.statusCode, error.message);
}
throw error;
}
}
Promise.all s typy
interface User {
id: number;
name: string;
}
interface Post {
id: number;
title: string;
}
async function loadAllData(): Promise<{ users: User[], posts: Post[] }> {
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json() as Promise<User[]>),
fetch('/api/posts').then(r => r.json() as Promise<Post[]>)
]);
// TS ví typy
return { users, posts };
}
Async metody v class
class UserService {
async getUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
async getAllUsers(): Promise<User[]> {
const response = await fetch('/api/users');
return response.json();
}
async createUser(data: Omit<User, 'id'>): Promise<User> {
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(data)
});
return response.json();
}
}
// Použití
const service = new UserService();
const user = await service.getUser(1);
console.log(user.name); // TS ví typ
Rozdíl JS vs TS
JavaScript:
- Async/await bez typů
- Nevíš, co
awaitvrátí - Chyby až za běhu
- Žádná kontrola návratového typu
TypeScript:
async function(): Promise- přesný typ návratové hodnoty- TS ví, co
awaitvrátí - Kontrola typů při kompilaci
- Autocomplete v IDE
Příklad:
// JS - nevíš co dostaneš
async function fetchData() {
const data = await fetch('/api/data');
return data.json(); // Co to vrací?
}
// TS - víš přesně
async function fetchData(): Promise<User> {
const response = await fetch('/api/data');
const user: User = await response.json();
return user; // ✅ TS ví, že je to User
}
Tip
💡 Async funkce vždy vrací Promise:
async function getValue() {
return 42;
}
// ❌ NELZE takhle
const value = getValue();
console.log(value); // Promise, ne 42!
// ✅ Použij await nebo .then()
const value = await getValue(); // 42 (v async funkci)
// Nebo:
getValue().then(v => console.log(v)); // 42
💡 Sekvenční vs Paralelní:
// ❌ Sekvenčně - 3 sekundy
async function slow() {
const a = await fetchA(); // 1s
const b = await fetchB(); // 1s
const c = await fetchC(); // 1s
}
// ✅ Paralelně - 1 sekunda
async function fast() {
const [a, b, c] = await Promise.all([
fetchA(), // Všechny
fetchB(), // běží
fetchC() // najednou!
]);
}
💡 Top-level await (ES2022):
// ❌ Nefunguje v starších prostředích
const data = await fetchData(); // Error!
// ✅ Použij async IIFE
(async () => {
const data = await fetchData();
console.log(data);
})();
💡 Await v loop - POZOR!:
// ❌ POMALÉ - sekvenčně
for (const id of [1, 2, 3]) {
const user = await fetchUser(id); // Čeká na každého!
}
// ✅ RYCHLÉ - paralelně
const users = await Promise.all(
[1, 2, 3].map(id => fetchUser(id))
);
💡 Error handling:
// ✅ VŽDY obalit v try/catch (nebo .catch())
async function fetchData() {
try {
const data = await fetch('/api/data');
return data.json();
} catch (error) {
console.error('Error:', error);
throw error; // Re-throw pokud chceš
}
}
// Nebo:
fetchData().catch(error => console.error(error));
💡 Await !== blokovací:
async function example() {
console.log('Start');
await timeout(1000);
console.log('After await');
}
example();
console.log('After call');
// Výstup:
// Start
// After call ← Nevyčkalo!
// (po 1s): After await
Kvíz
Které výroky o async/await jsou pravdivé?
✅ - Async funkce VŽDY vrací Promise - i když return hodnotu, automaticky se zabalí do Promise.resolve()
❌ - await lze použít POUZE uvnitř async funkcí (nebo v top-level await v ES2022 modulech)
❌ - await pozastaví pouze async funkci, NE celý program! Ostatní kód může běžet dál (event loop pokračuje)
✅ - async/await je syntactic sugar nad Promises - pod kapotou se stále používají Promises
🎯 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 →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
- 7.1 Synchronní vs asynchronní programování
- 7.2 Callbacks
- 07.03 Callback Hell
- 07.04 Promises úvod
- 07.05 Then a Catch
- 07.06 Promise.all
- 07.07 Promise.race
- 07.08 Async/Await
- 07.09 Try/Catch s async
- 07.10 Fetch API
- 7.11 Generátory
Struktura lekcí (souborový strom)
- 1.1 Úvod do JavaScriptu a TypeScriptu
- 1.2 Nastavení prostředí
- 1.3 První program
- 1.4 Proměnné: var, let, const
- 1.5 Datové typy - přehled
- 1.6 String (řetězce)
- 1.7 Number (čísla)
- 1.8 Boolean (pravda/nepravda)
- 1.9 Null a Undefined
- 1.10 Type Inference vs Annotations
- 1.11 Aritmetické operátory
- 1.12 Porovnávací operátory
- 1.13 Logické operátory
- 1.14 Komentáře
- 1.15 Console metody
- 03.01 Deklarace funkce
- 03.02 Function Expression
- 03.03 Arrow Functions
- 03.04 Parametry a argumenty
- 03.05 Return hodnoty
- 03.06 Výchozí parametry
- 03.07 Rest parametry
- 03.08 Co je Scope
- 03.09 Lexikální Scope
- 03.10 Řetězec Scope
- 03.11 Globální Scope
- 03.12 Životní Cyklus Proměnných
- 03.13 Omezení Scope
- 03.14 Použití Closures
- 03.15 Callback funkce
- 03.16 Higher-order Functions
- 03.17 IIFE
- 03.18 Void funkce
- 03.19 Rekurze
- v přípravě
- v přípravě
- v přípravě
- v přípravě
- 01 — Co je Next.js
- 02 — Vytvoření projektu
- 03 — Struktura projektu (app/)
- 04 — Page komponenty (page.js / page.tsx)
- 05 — Layout komponenty (layout.js / layout.tsx)
- 06 — File-based routing
- 07 — Dynamické routy ([id]/page.js)
- 08 — Link komponenta (navigace)
- 09 — Image komponenta (next/image)
- 10 — Metadata (title, description, Open Graph)
- 11 — Loading UI (loading.js / loading.tsx)
- 12 — Error handling (error.js / error.tsx)
- 13 — Not Found (not-found.js / not-found.tsx)
- v přípravě
- v přípravě
- v přípravě