Javascript promise – jak se neztratit v asynchronním kódu
Nemálokrát jsem se při psaní asynchronního kódu v Node.js zamotal do spletitých a nepřehledných callback funkcí. Promise nám nabízí jednoduchou a efektivní alternativu pro práci s asynchronním kódem v aplikaci. Umožňují nám psát aplikace přehlednější a krásnější.
Promise má tři základní stavy
- Pending – nevyřízený je takový, který ještě nebyl dokončen
- Fulfilled – splněný je takový, který byl úspěšně dokončen
- Rejected– nesplněný je takový, který skončil neúspěšně
Promisem může být vlastně cokoliv. A ani se nemusí jednat nutně o asynchronní blok kódu. V příkladu níže je jednoduchá synchronní validace requestu, která je definována jako promise. Díky tomu se může použít asynchronně a je stále zachována možnost do ní cokoliv předat jako parametr (např. request). Navíc má dva výsledky, může skončit buď úspěšně (resolve) s jakoukoliv návratovou hodnotou nebo neúspěšně (reject) taktéž s návratovou hodnotu. V příkladu níže je návratovou hodnotou chybová hláška o chybějících parametrech requestu.
validateUserRequest(req) {
return new Promise((resolve, reject) => {
if (!req.params) {
reject('Missing request params')
} else {
resolve('Request ok')
}
})
}
Vykonání tohoto promise potom uděláme takto.
this.validateUserRequest(req).then((response) => {
res.send(200, response)
}, (reason) => {
res.send(400, reason)
}).catch((e) => {
res.send(500, e);
});
V případě, že se promise vykoná jako reslove, bude navrácen http kód 200, v případě nevalidních parametrů se vrátí 400 a v případě fatální chyby spadne kód do catch větve a bude navrácen kód 500. Samozřejmostí je skládání promisů. Můžeme například definovat pole promisů a pomocí Promise.all počkat než se všechny dokončí.
const p1 = new Promise((resolve, reject) => {
...
});
const p2 = new Promise(function(resolve, reject) => {
...
});
Promise.all([p1, p2]).then((response) => {
...
}, (reason) => {
...
}).catch((e) => {
...
});
Asynchronicita je důležitou vlastností javascriptu a v aplikacích založených na nodeJs je ještě významnější, protože nodeJs běží na jednom vlákně a například synchronní čtení/zápis do souborů může mít velmi špatný vliv na výkon aplikace. Proto doporučuji promisy používat.