Implementace slibů v JavaScriptu

Foto Joshua Stannard na Unsplash

To, co na programování nejvíc miluji, je aha! okamžik, kdy začnete plně rozumět konceptu. I když to může trvat dlouho a žádné malé úsilí se tam dostat, určitě to stojí za to.

Myslím, že nejúčinnějším způsobem, jak posoudit (a pomoci zlepšit) náš stupeň porozumění danému subjektu, je vyzkoušet a aplikovat znalosti do skutečného světa. Nejenže to nám umožní identifikovat a nakonec vyřešit naše slabosti, ale také to může vrhnout nějaké světlo na to, jak věci fungují. Jednoduchý přístup k pokusům a omylům často odhalí ty detaily, které dříve zůstaly nepolapitelné.

S ohledem na to se domnívám, že učení, jak plnit sliby, bylo jedním z nejdůležitějších okamžiků na mé programovací cestě - poskytlo mi neocenitelný pohled na to, jak asynchronní kód funguje, a celkově z mě udělal lepšího programátora.

Doufám, že tento článek vám pomůže vyrovnat se s implementací slibů v JavaScriptu.

Zaměříme se na to, jak implementovat slibné jádro podle specifikace Promises / A + několika metodami API Bluebird. Budeme také používat přístup TDD s Jestem.

TypeScript se také hodí.

Vzhledem k tomu, že zde budeme pracovat na dovednostech implementace, předpokládám, že máte nějaké základní pochopení toho, co jsou sliby, a vágní pocit, jak fungují. Pokud tak neučiníte, je zde skvělé místo, kde začít.

Nyní, když to máme z cesty, jděte do toho a klonujte úložiště a začněme.

Jádro slibu

Jak víte, slib je objekt s následujícími vlastnostmi:

Pak

Metoda, která k našemu slibu připojuje obsluhu. Vrací nový příslib s hodnotou z předchozího mapovanou jednou z metod obsluhy.

Obsluhovatelé

Do té doby byla připojena řada obsluhy. Obslužný program je objekt obsahující dvě metody onSuccess a onFail, které jsou obě předávány jako argumenty do té doby (onSuccess, onFail).

Stát

Slib může být v jednom ze tří států: vyřešen, odmítnut nebo čekající.

Vyřešeno znamená, že buď všechno proběhlo hladce a my jsme dostali naši hodnotu, nebo jsme chybu zachytili a vyřešili.

Odmítnuto znamená, že jsme příslib buď odmítli, nebo byla vyvolána chyba a nechytili jsme ji.

Čekající znamená, že dosud nebyla volána ani metoda řešení, ani odmítnutí, a stále čekáme na hodnotu.

Termín „slib je splněn“ znamená, že slib je vyřešen nebo zamítnut.

Hodnota

Hodnota, kterou jsme vyřešili nebo odmítli.

Jakmile je hodnota nastavena, není možné ji změnit.

Testování

Podle přístupu TDD chceme napsat testy dříve, než přijde skutečný kód, takže to udělejme jen.

Zde jsou testy pro naše jádro:

Provádění našich testů

Velmi doporučuji použít rozšíření Jest pro Visual Studio Code. Spustí naše testy na pozadí a ukazuje nám výsledek přímo mezi řádky našeho kódu jako zelené a červené tečky pro úspěšné a neúspěšné testy.

Chcete-li zobrazit výsledky, otevřete konzolu „Výstup“ a vyberte kartu „Jest“.

Naše testy můžeme také spustit spuštěním následujícího příkazu:

npm run test

Bez ohledu na to, jak testy provádíme, vidíme, že se všechny vrátily negativní.

Pojďme to změnit.

Provádění jádra slibu

konstruktér

Náš konstruktor bere zpětné volání jako parametr.

Toto volání nazýváme this.resolve a this.reject jako argumenty.

Všimněte si, že za normálních okolností bychom na to vázali this.resolve a this.reject, ale zde jsme místo toho použili metodu třídy arrow.

setResult

Nyní musíme stanovit výsledek. Nezapomeňte, že výsledek musíme zpracovat správně, což znamená, že pokud to vrátí slib, musíme jej nejprve vyřešit.

Nejprve zkontrolujeme, zda stav čeká na vyřízení - pokud ano, je příslib již splněn a nemůžeme mu přiřadit žádnou novou hodnotu.

Pak musíme zkontrolovat, zda je hodnota použitelná. Jednoduše řečeno, pak použitelný je objekt, který má jako metodu.

Podle konvencí by se potomek měl chovat jako slib. Abychom dostali výsledek, zavoláme a předáme argumenty this.resolve a this.reject.

Poté, co se poté uzavře, zavolá jednu z našich metod a dá nám očekávanou neslibnou hodnotu.

Teď musíme zkontrolovat, zda je objekt použitelný.

Je důležité si uvědomit, že náš slib nebude nikdy synchronní, i když je kód uvnitř zpětného volání.

Provedeme zpoždění provádění až do další iterace smyčky událostí pomocí setTimeout.

Nyní zbývá už jen nastavit naši hodnotu a stav a poté provést registrované obslužné rutiny.

executeHandlers

Znovu se ujistěte, že stav čeká na vyřízení.

Stav slibu určuje, jakou funkci budeme používat.

Pokud je vyřešen, měli bychom provést onSuccess, jinak - onFail.

Nyní si vyjasníme naši řadu manipulátorů, abychom byli v bezpečí a neudělali nic náhodného v budoucnu. Psovod může být kdykoli připojen a proveden.

A o tom musíme dále diskutovat: způsob, jak připojit náš handler.

attachHandler

Je to opravdu tak jednoduché, jak se zdá. Prostě přidáme popisovač do našeho pole popisovačů a provedeme jej. A je to.

Nyní, aby to všechno dohromady, musíme implementovat tehdejší metodu.

pak

Pak vracíme slib a v zpětném volání připojíme handler, který se potom používá k čekání na vyřešení současného slibu.

Když k tomu dojde, bude proveden buď onSuccess, nebo onFail obsluhy, a my budeme odpovídajícím způsobem pokračovat.

Jedna věc, kterou si musíte zapamatovat, je, že není vyžadován žádný z handlerů, kteří byli předáni. Je však důležité, abychom se nesnažili provést něco, co by mohlo být nedefinováno.

Také v systému onFail, když je předán obsluha, vyřešíme vrácený slib, protože chyba byla zpracována.

chytit

Catch je vlastně jen abstrakce tehdejší metody.

A je to.

Konečně

Konečně je to také jen abstrakce za to, jak to udělat (konečně Cb, konečně Cb), protože o výsledek slibu je to jedno.

Ve skutečnosti také zachovává výsledek předchozího slibu a vrací jej. Takže to, co se konečně vrátí, na tom opravdu nezáleží.

toString

Vrátí pouze řetězec [objekt PQ].

Po implementaci jádra našich slibů můžeme nyní implementovat některé z výše uvedených metod Bluebird, které nám usnadní práci na slibech.

Další metody

Promise.resolve

Jak by to mělo fungovat.

Promise.reject

Jak by to mělo fungovat.

Promise.all

Jak by to mělo fungovat.

Věřím, že implementace je docela jednoduchá.

Počínaje collection.length, odpočítáváme s každou tryResolve, dokud nedosáhneme 0, což znamená, že každá položka kolekce byla vyřešena. Nově vytvořenou sbírku pak vyřešíme.

Promise.any

Jak by to mělo fungovat.

Jednoduše čekáme, až první hodnota vyřeší a vrátí ji ve slibu.

Promise.props

Jak by to mělo fungovat.

Provádíme iteraci nad klíči předaného objektu a vyřešíme každou hodnotu. Potom přidělíme hodnoty novému objektu a vyřešíme slíbení.

Promise.prototype.spread

Jak by to mělo fungovat.

Promise.delay

Jak by to mělo fungovat.

Použitím setTimeout jednoduše zpožďujeme vykonávání rozlišovací funkce o daný počet milisekund.

Promise.prototype.timeout

Jak by to mělo fungovat.

Tohle je trochu složitější.

Pokud setTimeout provede v našem slibu rychleji než tehdy, slib s naší speciální chybou odmítne.

Promise.promify

Jak by to mělo fungovat.

Aplikujeme na funkci všechny předané argumenty a navíc - jako poslední - dáme zpětné zpětné vyvolání chyby.

Promise.promifyVšechny

Jak by to mělo fungovat.

Provádíme iteraci nad klíči objektu a prominifikujeme jeho metody a ke každému názvu metodického slova Async přidáme.

Zabalení

Uvádíme zde jen několik ze všech metod Bluebird API, takže důrazně doporučuji prozkoumat, pohrát si s nimi a zkusit je implementovat.

Zpočátku se to může zdát těžké, ale nenechte se odradit - bylo by zbytečné, kdyby to bylo snadné.

Děkujeme za přečtení! Doufám, že jste tento článek shledali informativní a že vám to pomohlo pochopit koncept slibů a že od nynějška se budete cítit pohodlněji s jejich používáním nebo jednoduše psát asynchronní kód.

Pokud máte nějaké dotazy nebo připomínky, neváhejte je vložit do sekce komentářů níže nebo mi pošlete zprávu.

Podívejte se na moje sociální média!

Připojte se k mému zpravodaji!

Původně zveřejněno na www.mcieslar.com dne 4. srpna 2018.