7.2 Callbacks
Výuka
Co je callback?
Callback je funkce, kterou předáš jako argument do jiné funkce. Ta ji pak zavolá později - obvykle až dokončí nějakou asynchronní operaci.
Představ si to jako:
Jdeš k lékaři a řekneš: "Potřebuju výsledky testů. Až budou hotové (což může trvat), zavolej mi na tenhle telefon (callback) a povím ti, co s tím dál."
Doktor neblokuje tvůj den - ty mezitím můžeš dělat jiné věci. Až jsou výsledky hotové, callback se zavolá a ty zpracuješ informaci.
Proč callbacks?
V asynchronním kódu nemůžeš okamžitě dostat výsledek, protože operace trvá nějakou dobu (síť, disk, timer...). Potřebuješ způsob, jak říct: "Až to bude hotové, zavolej tuhle funkci s výsledkem."
Jak to funguje:
1. Spustíš async operaci (např. čtení souboru)
2. Předáš callback: "až bude hotovo, zavolej tuhle funkci"
3. Program pokračuje dál (NEČEKÁ!)
4. Až operace skončí → zavolá se callback s výsledkem
5. Callback zpracuje výsledek
Callbacks jsou VŠUDE v JavaScriptu
Callbacks nejsou jen pro asynchronní kód! Používají se i synchronně:
// Array metody - callbacks!
[1, 2, 3].map(num => num * 2); // callback: num => num * 2
[1, 2, 3].filter(num => num > 1); // callback: num => num > 1
// Event listeners - callbacks!
button.addEventListener('click', () => {
console.log('Kliknuto!'); // callback se zavolá při kliknutí
});
Rozdíl:
- Synchronní callback - zavolá se HNED (map, filter, forEach)
- Asynchronní callback - zavolá se POZDĚJI (setTimeout, readFile, fetch)
Continuation (pokračování programu)
Callback můžeš chápat jako pokračování programu. Rozděluje program na dvě části:
┌─────────────────┐
│ Část 1 (NOW) │ ← Provede se HNED
│ - hlavní kód │
└────────┬────────┘
│
↓
[ČEKÁNÍ na async operaci]
│
↓
┌────────┴────────┐
│ Část 2 (LATER) │ ← Provede se AŽ později
│ - callback │
└─────────────────┘
Příklad:
// A (NOW)
setTimeout(() => {
// C (LATER)
}, 1000);
// B (NOW)
Pořadí: A → B → (čekání) → C
Callback () => { // C } je druhá polovina programu - pokračování, které se provede až za sekundu.
Jak náš mozek přemýšlí vs jak fungují callbacks
Problém: Náš mozek plánuje synchronně (krok po kroku):
"Nejdřív udělám A, pak B, pak C."
Ale callbacks nás nutí přemýšlet asynchronně:
"Udělám A, pak nastartuju B (který trvá), mezitím udělám C, a až B skončí, zavolá se můj callback s výsledkem B..."
To je těžké! Proto je async kód s callbacky náročný na čtení a pochopení.
Srovnání:
// Synchronní - jasné pořadí (mozek tohle chápe)
z = x;
x = y;
y = z;
// Asynchronní - pořadí se "rozpadá"
doA(() => {
doC();
doD(() => {
doF();
});
doE();
});
doB();
// Pořadí: A → B → C → D → E → F (WTF?!)
JavaScript
Synchronní callback (okamžité zavolání)
// Funkce přijímá callback jako parametr
function doSomething(callback) {
const result = 5 + 3;
callback(result); // Zavolá callback HNED
}
// Použití
doSomething((result) => {
console.log('Výsledek:', result); // 8
});
console.log('Pokračuji dál...');
// Výstup:
// Výsledek: 8
// Pokračuji dál...
Co se stalo? Callback se zavolal synchronně - HNED, během běhu doSomething().
Asynchronní callback (pozdější zavolání)
// Funkce s asynchronním callbackem
function fetchData(callback) {
setTimeout(() => {
const data = { name: 'Jan', age: 25 };
callback(data); // Zavolá callback AŽ PO 1 sekundě
}, 1000);
}
// Použití
fetchData((data) => {
console.log('Data načtena:', data);
});
console.log('Pokračuji dál...');
// Výstup (okamžitě):
// Pokračuji dál...
// (po 1s): Data načtena: { name: 'Jan', age: 25 }
Co se stalo?
fetchDataspustil timeout a VRÁTIL SE OKAMŽITĚ- Program pokračoval dál →
console.log('Pokračuji dál...') - Až za sekundu timeout zavolal callback
Error-first callback pattern (Node.js konvence)
V Node.js se používá konvence: první parametr callbacku je error (pokud nastala chyba), druhý je data (pokud vše OK).
Proč? Musíš řešit dvě věci:
- ✅ Co dělat, když operace uspěje (data)
- ❌ Co dělat, když operace selže (error)
// Error-first callback pattern
function readFile(filename, callback) {
setTimeout(() => {
if (filename === 'error.txt') {
// Chyba - první parametr je Error
callback(new Error('Soubor nenalezen'), null);
} else {
// Úspěch - první parametr je null
callback(null, 'Obsah souboru');
}
}, 1000);
}
// Použití
readFile('data.txt', (err, data) => {
if (err) {
console.error('Chyba:', err.message);
return; // Skonči, nezpracovávej data
}
console.log('Data:', data);
});
Konvence:
callback(error, null)- chyba nastalacallback(null, data)- úspěch, máme data
Vždy nejdřív kontroluj error!
Reálné příklady callbacků
// 1. setTimeout (časovač)
setTimeout(() => {
console.log('Po 2 sekundách');
}, 2000);
// 2. addEventListener (události v prohlížeči)
button.addEventListener('click', (event) => {
console.log('Kliknuto!', event);
});
// 3. Array metody (synchronní callbacks)
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((num) => {
console.log(num * 2);
});
const doubled = numbers.map((num) => num * 2);
// [2, 4, 6, 8, 10]
const evens = numbers.filter((num) => num % 2 === 0);
// [2, 4]
// 4. HTTP request (fetch s then - předchůdce async/await)
fetch('/api/users')
.then(response => response.json())
.then(users => {
console.log('Users:', users);
});
TypeScript
TypeScript přidává typy pro callbacks, takže víš přesně, co callback dostane a co má vrátit.
Typované callback funkce
// Definice typu pro callback
type Callback<T> = (data: T) => void;
// Callback který dostane číslo
type NumberCallback = (num: number) => void;
// Callback který dostane string
type StringCallback = (str: string) => void;
// Použití v funkci
function fetchUser(id: number, callback: Callback<User>): void {
setTimeout(() => {
const user: User = { id, name: 'Jan', age: 25 };
callback(user); // TS ví, že callback dostane User
}, 1000);
}
// Použití
fetchUser(1, (user: User) => {
console.log(user.name); // TS ví, že user má property name
// console.log(user.email); // ❌ Error - User nemá email
});
Error-first callback s typy
// Typ pro error-first callback
type ErrorCallback<T> = (error: Error | null, data: T | null) => void;
function loadData(
filename: string,
callback: ErrorCallback<string>
): void {
setTimeout(() => {
if (filename.endsWith('.txt')) {
callback(null, 'Data loaded'); // Úspěch
} else {
callback(new Error('Invalid file'), null); // Chyba
}
}, 500);
}
// Použití
loadData('data.txt', (err, data) => {
if (err) {
console.error(err.message);
return;
}
// TS ví, že data je string (pokud není null)
console.log(data.toUpperCase()); // ✅ OK
});
Generický callback
// Generická funkce s callbackem
function processAsync<T>(
value: T,
callback: (result: T) => void
): void {
setTimeout(() => callback(value), 100);
}
// TS automaticky odvodí typ T
processAsync<number>(42, (result) => {
console.log(result * 2); // TS ví, že result je number
});
processAsync<string>('hello', (result) => {
console.log(result.toUpperCase()); // TS ví, že result je string
});
Interface pro User (pro příklady výše)
interface User {
id: number;
name: string;
age: number;
}
Rozdíl JS vs TS
JavaScript:
- Callbacks bez typů - nevíš, co callback dostane
- Žádná kontrola v IDE
- Chyby až za běhu programu
TypeScript:
- Typované callbacks - přesně víš, co callback dostane a vrátí
- Autocomplete v IDE pro parametry callbacku
- Kontrola typů PŘED spuštěním
- Bezpečnější kód
// JS - nevíš co dostaneš
fetchData((data) => {
console.log(data.name); // Možná chyba za běhu (pokud data nemá name)
});
// TS - víš přesně
fetchData((data: User) => {
console.log(data.name); // ✅ TS ví, že má name
// console.log(data.email); // ❌ Error - User nemá email
});
Tip
💡 Error-first pattern (Node.js konvence):
// Konvence: první parametr = error
function operation(callback) {
if (/* něco se pokazilo */) {
callback(new Error('Popis chyby'), null);
} else {
callback(null, data);
}
}
// Použití - VŽDY nejdřív zkontroluj error!
operation((err, data) => {
if (err) return console.error(err); // Skonči při chybě
console.log(data); // Zpracuj data
});
💡 Callback vs Handler:
// Callback - zavolá se JEDNOU
setTimeout(callback, 1000);
readFile('file.txt', callback);
// Handler - může být zavolán VÍCEKRÁT
button.addEventListener('click', handler);
websocket.on('message', handler);
💡 Arrow functions pro callbacks (kratší zápis):
// Delší zápis (klasická funkce)
setTimeout(function() {
console.log('Hotovo');
}, 1000);
// Kratší zápis (arrow function)
setTimeout(() => {
console.log('Hotovo');
}, 1000);
// Jednořádkový (nejkratší)
setTimeout(() => console.log('Hotovo'), 1000);
💡 Callback "hell" bude v další lekci:
Callbacks mají velký problém - vnořování. Když potřebuješ několik async operací za sebou:
// Pyramid of doom (callback hell) - PŘÍŠTĚ!
readFile('file1.txt', (err, data1) => {
readFile('file2.txt', (err, data2) => {
readFile('file3.txt', (err, data3) => {
// Už nevíš, kde jsi... 😵
});
});
});
To si ukážeme v 7.3 Callback Hell.
Kvíz
Které výroky jsou pravdivé?
✅ - Callback = funkce jako argument, kterou někdo jiný zavolá
❌ - Callbacks se používají i synchronně (map, forEach, filter, reduce)
✅ - Node.js konvence: callback(error, data) - error je vždy první
❌ - TS často automaticky odvodí typ callbacku z kontextu (type inference)
🎯 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ě