Ono celé slavné async/await je jen mnoho povyku pro nic, je to nic nepřinášející zhnusnění kódu. Čistě formálně je to jen zbytečně složitě vyjádřená monáda.
Nemohl bys uvést ukázku pěkného kódu, který se tím zhnusí? Jak vypadá jednoduše vyjádřená monáda?
Tak když vezmu
Purescript Aff monad, což je v podstatě přesně to, co řeší async-await.
Tak když vezmu ty příklady - ten originál z té
stránky:
All getJSON operations will happen in parallel, and the application will wait until all requests are complete before adding them all to the page at once.
(await Promise.all(urls.map(getJSON))).forEach(j => addToPage(j.html));
-- vs.
parTraverse getJSON urls >>= traverse (addToPage _.html)
All getJSON operations will happen in parallel, and each object will be added to the page as it arrives (possibly out of order).
await Promise.all(urls.map(getJSON).map(async j => addToPage((await j).html)));
-- vs.
parTraverse_ (getJSON >=> addToPage (_.html)) urls
All getJSON operations will happen in parallel, with the results being added to the page sequentially as they come in.
for (let j of urls.map(getJSON)) {
addToPage((await j).html);
}
A tady tohle standardně nejde, protože to je imperativní kód, nicméně když si definujeme malé funkce...
async f = do
v <- makeVar
forkAff (f >>= putVar v)
pure v
await = takeVar
Take ten kód můžeme napsat:
parTraverse (\url -> async (getJSON url)) urls >>= traverse_ (\promise -> await promise >>= addToPage _.html)
(nebo zkráceně)
parTraverse (async <<< getJSON) urls >>= traverse_ (await promise >=> addToPage _.html)
A ta sranda je, že parTraverse je jenom normální funkce, která někde volá "traverse" (obdoba forEach), takže funguje se všemi strukturami, které podporují Traversable. A na implementaci "async" a "await" (který je navíc potřeba jen, když nepoužíváme sekvenční kód) není potřeba modifikovat jazyk, ale dají se normálně naprogramovat...