|
1 |
| -# Promisification |
| 1 | +# Promisifikace |
2 | 2 |
|
3 |
| -"Promisification" is a long word for a simple transformation. It's the conversion of a function that accepts a callback into a function that returns a promise. |
| 3 | +„Promisifikace“ je dlouhý výraz pro jednoduchou transformaci. Je to převod funkce, která přijímá callback, na funkci, která vrací příslib. |
4 | 4 |
|
5 |
| -Such transformations are often required in real-life, as many functions and libraries are callback-based. But promises are more convenient, so it makes sense to promisify them. |
| 5 | +Takové transformace jsou ve skutečném životě často požadovány, jelikož mnoho funkcí a knihoven je založeno na callbaccích. Přísliby jsou však vhodnější, takže promisifikace těchto funkcí dává smysl. |
6 | 6 |
|
7 |
| -For better understanding, let's see an example. |
| 7 | +Pro lepší porozumění se podívejme na příklad. |
8 | 8 |
|
9 |
| -For instance, we have `loadScript(src, callback)` from the chapter <info:callbacks>. |
| 9 | +Máme například funkci `načtiSkript(zdroj, callback)` z kapitoly <info:callbacks>. |
10 | 10 |
|
11 | 11 | ```js run
|
12 |
| -function loadScript(src, callback) { |
13 |
| - let script = document.createElement('script'); |
14 |
| - script.src = src; |
| 12 | +function načtiSkript(zdroj, callback) { |
| 13 | + let skript = document.createElement('script'); |
| 14 | + skript.src = zdroj; |
15 | 15 |
|
16 |
| - script.onload = () => callback(null, script); |
17 |
| - script.onerror = () => callback(new Error(`Script load error for ${src}`)); |
| 16 | + skript.onload = () => callback(null, skript); |
| 17 | + skript.onerror = () => callback(new Error(`Chyba načítání skriptu pro ${zdroj}`)); |
18 | 18 |
|
19 |
| - document.head.append(script); |
| 19 | + document.head.append(skript); |
20 | 20 | }
|
21 | 21 |
|
22 |
| -// usage: |
23 |
| -// loadScript('path/script.js', (err, script) => {...}) |
| 22 | +// použití: |
| 23 | +// načtiSkript('path/script.js', (chyba, skript) => {...}) |
24 | 24 | ```
|
25 | 25 |
|
26 |
| -The function loads a script with the given `src`, and then calls `callback(err)` in case of an error, or `callback(null, script)` in case of successful loading. That's a widespread agreement for using callbacks, we saw it before. |
| 26 | +Tato funkce načte skript ze zadaného zdroje `zdroj` a pak volá `callback(chyba)` v případě chyby nebo `callback(null, skript)` v případě úspěšného načtení. To je široce rozšířená úmluva pro používání callbacků, kterou jsme již viděli. |
27 | 27 |
|
28 |
| -Let's promisify it. |
| 28 | +Promisifikujme tuto funkci. |
29 | 29 |
|
30 |
| -We'll make a new function `loadScriptPromise(src)`, that does the same (loads the script), but returns a promise instead of using callbacks. |
| 30 | +Vytvořme novou funkci `načtiSkriptPříslibem(zdroj)`, která udělá totéž (načte skript), ale místo používání callbacků vrátí příslib. |
31 | 31 |
|
32 |
| -In other words, we pass it only `src` (no `callback`) and get a promise in return, that resolves with `script` when the load is successful, and rejects with the error otherwise. |
| 32 | +Jinými slovy, předáme do ní jenom `zdroj` (ne `callback`) a jako návratovou hodnotu obdržíme příslib, který se splní s hodnotou `skript`, bude-li načítání úspěšné, a jinak se zamítne s chybou. |
33 | 33 |
|
34 |
| -Here it is: |
| 34 | +Zde je: |
35 | 35 | ```js
|
36 |
| -let loadScriptPromise = function(src) { |
37 |
| - return new Promise((resolve, reject) => { |
38 |
| - loadScript(src, (err, script) => { |
39 |
| - if (err) reject(err); |
40 |
| - else resolve(script); |
| 36 | +let načtiSkriptPříslibem = function(zdroj) { |
| 37 | + return new Promise((splň, zamítni) => { |
| 38 | + načtiSkript(zdroj, (chyba, skript) => { |
| 39 | + if (chyba) zamítni(chyba); |
| 40 | + else splň(skript); |
41 | 41 | });
|
42 | 42 | });
|
43 | 43 | };
|
44 | 44 |
|
45 |
| -// usage: |
46 |
| -// loadScriptPromise('path/script.js').then(...) |
| 45 | +// použití: |
| 46 | +// načtiSkriptPříslibem('path/script.js').then(...) |
47 | 47 | ```
|
48 | 48 |
|
49 |
| -As we can see, the new function is a wrapper around the original `loadScript` function. It calls it providing its own callback that translates to promise `resolve/reject`. |
| 49 | +Jak vidíme, nová funkce je obalem okolo původní funkce `načtiSkript`. Zavolá ji a poskytne jí svůj vlastní callback, který se převede na příslib `splň/zamítni`. |
50 | 50 |
|
51 |
| -Now `loadScriptPromise` fits well in promise-based code. If we like promises more than callbacks (and soon we'll see more reasons for that), then we will use it instead. |
| 51 | +Nyní `načtiSkriptPříslibem` dobře zapadne do kódu založeného na příslibech. Máme-li raději přísliby než callbacky (a brzy pro to uvidíme další důvody), použijeme místo původní funkce tuto. |
52 | 52 |
|
53 |
| -In practice we may need to promisify more than one function, so it makes sense to use a helper. |
| 53 | +V praxi můžeme potřebovat promisifikovat více než jednu funkci, takže dává smysl použít pomocnou funkci. |
54 | 54 |
|
55 |
| -We'll call it `promisify(f)`: it accepts a to-promisify function `f` and returns a wrapper function. |
| 55 | +Nazveme ji `promisifikuj(f)`: bude přijímat funkci `f`, která má být promisifikována, a vrátí obalovou funkci. |
56 | 56 |
|
57 | 57 | ```js
|
58 |
| -function promisify(f) { |
59 |
| - return function (...args) { // return a wrapper-function (*) |
60 |
| - return new Promise((resolve, reject) => { |
61 |
| - function callback(err, result) { // our custom callback for f (**) |
62 |
| - if (err) { |
63 |
| - reject(err); |
| 58 | +function promisifikuj(f) { |
| 59 | + return function (...argumenty) { // vrátí obalovou funkci (*) |
| 60 | + return new Promise((splň, zamítni) => { |
| 61 | + function callback(chyba, výsledek) { // náš vlastní callback pro f (**) |
| 62 | + if (chyba) { |
| 63 | + zamítni(chyba); |
64 | 64 | } else {
|
65 |
| - resolve(result); |
| 65 | + splň(výsledek); |
66 | 66 | }
|
67 | 67 | }
|
68 | 68 |
|
69 |
| - args.push(callback); // append our custom callback to the end of f arguments |
| 69 | + argumenty.push(callback); // připojí náš vlastní callback na konec argumentů funkce f |
70 | 70 |
|
71 |
| - f.call(this, ...args); // call the original function |
| 71 | + f.call(this, ...argumenty); // zavolá původní funkci |
72 | 72 | });
|
73 | 73 | };
|
74 | 74 | }
|
75 | 75 |
|
76 |
| -// usage: |
77 |
| -let loadScriptPromise = promisify(loadScript); |
78 |
| -loadScriptPromise(...).then(...); |
| 76 | +// použití: |
| 77 | +let načtiSkriptPříslibem = promisifikuj(načtiSkript); |
| 78 | +načtiSkriptPříslibem(...).then(...); |
79 | 79 | ```
|
80 | 80 |
|
81 |
| -The code may look a bit complex, but it's essentially the same that we wrote above, while promisifying `loadScript` function. |
| 81 | +Kód může vypadat trochu složitě, ale v zásadě je to totéž, co jsme napsali výše, když jsme promisifikovali funkci `načtiSkript`. |
82 | 82 |
|
83 |
| -A call to `promisify(f)` returns a wrapper around `f` `(*)`. That wrapper returns a promise and forwards the call to the original `f`, tracking the result in the custom callback `(**)`. |
| 83 | +Volání `promisifikuj(f)` vrátí obal okolo `f` `(*)`. Tento obal vrátí příslib, předá volání původní funkci `f` a výsledek zpracuje ve vlastním callbacku `(**)`. |
84 | 84 |
|
85 |
| -Here, `promisify` assumes that the original function expects a callback with exactly two arguments `(err, result)`. That's what we encounter most often. Then our custom callback is in exactly the right format, and `promisify` works great for such a case. |
| 85 | +Zde funkce `promisifikuj` předpokládá, že původní funkce očekává callback s právě dvěma argumenty `(chyba, výsledek)`. S tím se setkáváme nejčastěji. Náš vlastní callback je přesně ve správném formátu a funkce `promisifikuj` v takovém případě funguje skvěle. |
86 | 86 |
|
87 |
| -But what if the original `f` expects a callback with more arguments `callback(err, res1, res2, ...)`? |
| 87 | +Ale co když původní funkce `f` očekává callback s více argumenty `callback(chyba, výsledek1, výsledek2, ...)`? |
88 | 88 |
|
89 |
| -We can improve our helper. Let's make a more advanced version of `promisify`. |
| 89 | +Můžeme naši pomocnou funkci vylepšit. Vytvořme pokročilejší verzi `promisifikuj`. |
90 | 90 |
|
91 |
| -- When called as `promisify(f)` it should work similar to the version above. |
92 |
| -- When called as `promisify(f, true)`, it should return the promise that resolves with the array of callback results. That's exactly for callbacks with many arguments. |
| 91 | +- Když bude volána jako `promisifikuj(f)`, měla by fungovat podobně jako uvedená verze. |
| 92 | +- Když bude volána jako `promisifikuj(f, true)`, měla by vrátit příslib, který se splní s polem výsledků callbacku. To je určeno právě pro callbacky s mnoha argumenty. |
93 | 93 |
|
94 | 94 | ```js
|
95 |
| -// promisify(f, true) to get array of results |
96 |
| -function promisify(f, manyArgs = false) { |
97 |
| - return function (...args) { |
98 |
| - return new Promise((resolve, reject) => { |
99 |
| - function *!*callback(err, ...results*/!*) { // our custom callback for f |
100 |
| - if (err) { |
101 |
| - reject(err); |
| 95 | +// promisifikuj(f, true) pro získání pole výsledků |
| 96 | +function promisifikuj(f, víceArgumentů = false) { |
| 97 | + return function (...argumenty) { |
| 98 | + return new Promise((splň, zamítni) => { |
| 99 | + function *!*callback(chyba, ...výsledky*/!*) { // náš vlastní callback pro f |
| 100 | + if (chyba) { |
| 101 | + zamítni(chyba); |
102 | 102 | } else {
|
103 |
| - // resolve with all callback results if manyArgs is specified |
104 |
| - *!*resolve(manyArgs ? results : results[0]);*/!* |
| 103 | + // je-li uvedeno víceArgumentů, splní se se všemi výsledky callbacku |
| 104 | + *!*splň(víceArgumentů ? výsledky : výsledky[0]);*/!* |
105 | 105 | }
|
106 | 106 | }
|
107 | 107 |
|
108 |
| - args.push(callback); |
| 108 | + argumenty.push(callback); |
109 | 109 |
|
110 |
| - f.call(this, ...args); |
| 110 | + f.call(this, ...argumenty); |
111 | 111 | });
|
112 | 112 | };
|
113 | 113 | }
|
114 | 114 |
|
115 |
| -// usage: |
116 |
| -f = promisify(f, true); |
117 |
| -f(...).then(arrayOfResults => ..., err => ...); |
| 115 | +// použití: |
| 116 | +f = promisifikuj(f, true); |
| 117 | +f(...).then(poleVýsledků => ..., chyba => ...); |
118 | 118 | ```
|
119 | 119 |
|
120 |
| -As you can see it's essentially the same as above, but `resolve` is called with only one or all arguments depending on whether `manyArgs` is truthy. |
| 120 | +Jak vidíte, je to v zásadě totéž jako výše, ale `splň` se volá buď jen s jedním, nebo se všemi argumenty, podle toho, zda je argument `víceArgumentů` pravdivý. |
121 | 121 |
|
122 |
| -For more exotic callback formats, like those without `err` at all: `callback(result)`, we can promisify such functions manually without using the helper. |
| 122 | +Pro exotičtější formáty callbacků, např. takové, které vůbec neobsahují argument `chyba`: `callback(výsledek)`, můžeme takové funkce promisifikovat ručně bez použití pomocné funkce. |
123 | 123 |
|
124 |
| -There are also modules with a bit more flexible promisification functions, e.g. [es6-promisify](https://github.com/digitaldesignlabs/es6-promisify). In Node.js, there's a built-in `util.promisify` function for that. |
| 124 | +Existují i moduly s trochu flexibilnějšími promisifikačními funkcemi, např. [es6-promisify](https://github.com/digitaldesignlabs/es6-promisify). V Node.js k tomu slouží zabudovaná funkce `util.promisify`. |
125 | 125 |
|
126 | 126 | ```smart
|
127 |
| -Promisification is a great approach, especially when you use `async/await` (covered later in the chapter <info:async-await>), but not a total replacement for callbacks. |
| 127 | +Promisifikace je skvělý přístup, zvláště když používáte `async/await` (bude vysvětleno později v kapitole <info:async-await>), ale není to úplná náhrada za callbacky. |
128 | 128 |
|
129 |
| -Remember, a promise may have only one result, but a callback may technically be called many times. |
| 129 | +Pamatujte, že příslib může mít jen jediný výsledek, ale callback lze technicky volat mnohokrát. |
130 | 130 |
|
131 |
| -So promisification is only meant for functions that call the callback once. Further calls will be ignored. |
| 131 | +Promisifikace má tedy smysl jen u funkcí, které volají callback pouze jednou. Další volání budou ignorována. |
132 | 132 | ```
|
0 commit comments