Programování

Asynchronous JavaScript: Callbacks and promises explains

Nakládání s asynchronním kódem, což znamená kód, který se nespustí okamžitě, jako jsou webové požadavky nebo časovače, může být obtížné. JavaScript nám poskytuje dva způsoby, jak zvládnout asynchronní chování: zpětná volání a sliby.

Zpětná volání byla jediným nativně podporovaným způsobem řešení asynchronního kódu do roku 2016, kdy Slib objekt byl zaveden do jazyka. Vývojáři JavaScriptu však podobnou funkcionalitu implementovali již řadu let, než na scénu dorazily sliby. Podívejme se na některé rozdíly mezi zpětnými voláními a sliby a podívejme se, jak řešíme koordinaci několika slibů.

Asynchronní funkce, které používají zpětná volání, berou funkci jako parametr, který bude volán po dokončení práce. Pokud jste něco podobného použili setTimeout v prohlížeči jste použili zpětná volání.

// Zpětné volání můžete definovat samostatně ...

nech myCallback = () => {

console.log ('Volal!');

};

setTimeout (myCallback, 3000);

//… ale je také běžné vidět zpětná volání definovaná inline

setTimeout (() => {

console.log ('Volal!');

}, 3000);

Funkce, která přijímá zpětné volání, ji obvykle bere jako svůj poslední argument. Toto není výše uvedený případ, takže předstírejme, že se jmenuje nová funkce Počkejte to je jako setTimeout ale vezme první dva argumenty v opačném pořadí:

// Použili bychom naši novou funkci takto:

waitCallback (3000, () => {

console.log ('Volal!');

});

Vnořená zpětná volání a pyramida zkázy

Zpětná volání fungují dobře při zpracování asynchronního kódu, ale jsou komplikovaná, když začnete koordinovat více asynchronních funkcí. Například pokud jsme chtěli počkat dvě sekundy a něco zaznamenat, pak počkat tři sekundy a přihlásit něco jiného, ​​pak počkat čtyři sekundy a přihlásit něco jiného, ​​naše syntaxe se stane hluboce vnořenou.

// Použili bychom naši novou funkci takto:

waitCallback (2000, () => {

console.log ('První zpětné volání!');

waitCallback (3000, () => {

console.log ('Druhé zpětné volání!');

waitCallback (4000, () => {

console.log ('Třetí zpětné volání!');

    });

  });

});

To se může zdát jako triviální příklad (a je to), ale není neobvyklé zadávat několik webových požadavků v řadě na základě výsledků vrácení předchozího požadavku. Pokud vaše knihovna AJAX používá zpětná volání, zobrazí se výše uvedená struktura. V příkladech, které jsou hluboce vnořeny, uvidíte to, co se označuje jako pyramida zkázy, která dostává svůj název podle tvaru pyramidy vytvořeného v odsazeném prázdném prostoru na začátku řádků.

Jak vidíte, náš kód je strukturálně rozbitý a těžší čitelný při práci s asynchronními funkcemi, které se musí stát postupně. Ale bude to ještě složitější. Představte si, že bychom chtěli zahájit tři nebo čtyři webové požadavky a provést nějaký úkol až poté, co se všechny vrátí. Doporučuji vám, abyste se o to pokusili, pokud jste se s touto výzvou dosud nesetkali.

Snadnější asynchronizace se sliby

Promises poskytuje flexibilnější API pro řešení asynchronních úkolů. Vyžaduje, aby byla funkce zapsána tak, že vrací a Slib objekt, který má některé standardní funkce pro zpracování následného chování a koordinaci několika slibů. Pokud naše waitCallback funkce byla Slib-založeno, zabralo by to jen jeden argument, což je milisekunda čekání. Jakákoli následná funkce by byla připoutaný mimo slib. Náš první příklad by vypadal takto:

nech myHandler = () => {

console.log („Volal!“);

};

waitPromise (3000). potom (myHandler);

Ve výše uvedeném příkladu waitPromise (3000) vrací a Slib objekt, který má některé metody, které můžeme použít, například pak. Pokud bychom chtěli vykonávat několik asynchronních funkcí jeden po druhém, mohli bychom se vyhnout pyramidě zkázy pomocí slibů. Ten kód, přepsaný tak, aby podporoval náš nový slib, by vypadal takto:

// Bez ohledu na to, kolik sekvenčních asynchronních úkolů máme, pyramidu nikdy nevyrobíme.

waitPromise (2000)

.tak (() => {

console.log ('První zpětné volání!');

návrat waitPromise (3000);

  })

.tak (() => {

console.log ('Druhé zpětné volání!');

návrat waitPromise (4000);

  })

.tak (() => {

console.log ('Druhé zpětné volání!');

návrat waitPromise (4000);

  });

Ještě lépe, pokud potřebujeme koordinovat asynchronní úkoly, které podporují Promises, můžeme použít Všechno, což je statická metoda na Slib objekt, který vezme několik slibů a spojí je do jednoho. Vypadalo by to jako:

Promise.all ([

waitPromise (2000),

waitPromise (3000),

waitPromise (4000)

]). then (() => console.log ('Everything is done!'));

Příští týden se budeme hlouběji zabývat tím, jak sliby fungují a jak je idiomaticky používat. Pokud se právě učíte JavaScript nebo máte zájem otestovat své znalosti, zkuste to waitCallback nebo se pokuste dosáhnout ekvivalentu Promise.all se zpětnými voláními.

Jako vždy mě kontaktujte na Twitteru s jakýmikoli komentáři nebo dotazy.

$config[zx-auto] not found$config[zx-overlay] not found