Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork3
Promisification#197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
Uh oh!
There was an error while loading.Please reload this page.
Merged
Promisification#197
Changes fromall commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
136 changes: 68 additions & 68 deletions1-js/11-async/06-promisify/article.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,132 +1,132 @@ | ||
#Promisifikace | ||
„Promisifikace“ je dlouhý výraz pro jednoduchou transformaci. Je to převod funkce, která přijímácallback, na funkci, která vrací příslib. | ||
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. | ||
Pro lepší porozumění se podívejme na příklad. | ||
Máme například funkci `načtiSkript(zdroj, callback)`z kapitoly <info:callbacks>. | ||
```js run | ||
functionnačtiSkript(zdroj, callback) { | ||
letskript = document.createElement('script'); | ||
skript.src =zdroj; | ||
skript.onload = () => callback(null,skript); | ||
skript.onerror = () => callback(new Error(`Chyba načítání skriptu pro ${zdroj}`)); | ||
document.head.append(skript); | ||
} | ||
//použití: | ||
//načtiSkript('path/script.js', (chyba, skript) => {...}) | ||
``` | ||
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. | ||
Promisifikujme tuto funkci. | ||
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. | ||
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. | ||
Zde je: | ||
```js | ||
letnačtiSkriptPříslibem = function(zdroj) { | ||
return new Promise((splň, zamítni) => { | ||
načtiSkript(zdroj, (chyba, skript) => { | ||
if (chyba) zamítni(chyba); | ||
elsesplň(skript); | ||
}); | ||
}); | ||
}; | ||
//použití: | ||
//načtiSkriptPříslibem('path/script.js').then(...) | ||
``` | ||
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`. | ||
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. | ||
V praxi můžeme potřebovat promisifikovat více než jednu funkci, takže dává smysl použít pomocnou funkci. | ||
Nazveme ji `promisifikuj(f)`:bude přijímat funkci`f`, která má být promisifikována, a vrátí obalovou funkci. | ||
```js | ||
functionpromisifikuj(f) { | ||
return function (...argumenty) { //vrátí obalovou funkci (*) | ||
return new Promise((splň, zamítni) => { | ||
function callback(chyba, výsledek) { //náš vlastní callbackpro f (**) | ||
if (chyba) { | ||
zamítni(chyba); | ||
} else { | ||
splň(výsledek); | ||
} | ||
} | ||
argumenty.push(callback); //připojí náš vlastní callbackna konec argumentů funkce f | ||
f.call(this, ...argumenty); //zavolá původní funkci | ||
}); | ||
}; | ||
} | ||
//použití: | ||
letnačtiSkriptPříslibem =promisifikuj(načtiSkript); | ||
načtiSkriptPříslibem(...).then(...); | ||
``` | ||
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`. | ||
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 `(**)`. | ||
Zde funkce `promisifikuj` předpokládá, že původní funkce očekávácallbacks právě dvěma argumenty `(chyba, výsledek)`.S tím se setkáváme nejčastěji. Náš vlastnícallbackje přesně ve správném formátu a funkce `promisifikuj` v takovém případě funguje skvěle. | ||
Ale co když původní funkce `f`očekávácallbacks více argumenty `callback(chyba, výsledek1, výsledek2, ...)`? | ||
Můžeme naši pomocnou funkci vylepšit. Vytvořme pokročilejší verzi `promisifikuj`. | ||
-Když bude volána jako `promisifikuj(f)`, měla by fungovat podobně jako uvedená verze. | ||
-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. | ||
```js | ||
//promisifikuj(f, true)pro získání pole výsledků | ||
functionpromisifikuj(f,víceArgumentů = false) { | ||
return function (...argumenty) { | ||
return new Promise((splň, zamítni) => { | ||
function *!*callback(chyba, ...výsledky*/!*) { //náš vlastní callbackpro f | ||
if (chyba) { | ||
zamítni(chyba); | ||
} else { | ||
//je-li uvedeno víceArgumentů, splní se se všemi výsledky callbacku | ||
*!*splň(víceArgumentů ?výsledky :výsledky[0]);*/!* | ||
} | ||
} | ||
argumenty.push(callback); | ||
f.call(this, ...argumenty); | ||
}); | ||
}; | ||
} | ||
//použití: | ||
f =promisifikuj(f, true); | ||
f(...).then(poleVýsledků => ...,chyba => ...); | ||
``` | ||
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ý. | ||
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. | ||
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`. | ||
```smart | ||
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. | ||
Pamatujte, že příslib může mít jen jediný výsledek, alecallbacklze technicky volat mnohokrát. | ||
Promisifikace má tedy smysl jen u funkcí, které volajícallbackpouze jednou. Další volání budou ignorována. | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.