2. CO TO JE GENERÁTOR?
Funkce, která jde pozastavit,
a implementuje iterator
interface.
Může z ní „vypadnout“ více
hodnot po sobě.
3. CO TO JE ITERÁTOR?
• Iterátor je cokoliv, co implentuje jeho rozhraní, jak je
definované na MDN
https://developer.mozilla.org/en/docs/Web/JavaScript/Referen
ce/Iteration_protocols
• Slouží k procházení iterovatelných objektů – iterable
4. ITERABLE VS ITERATOR
• Iterable je objekt, jehož prvky je možné procházet jeden po
druhém (Array, Map, Set, ale také třeba String)
• Každý takový objekt může mít více iterátorů, které ho
procházejí nezávisle na sobě
5. METODY ITERÁTORU
• Iterátor má 2 hlavní metody
• .next() – vrací další objekt v řadě a říká, jestli už jsme došli na konec
• .throw() – slouží k vyvolání vyjímky uvnitř iterátoru. Rozbije ho
.next() vrací objekt v tomto tvaru
{
value: "hodnota", // aktuálně vrácený prvek
done: boolean // došli už jsme na konec iterace?
}
6. KDE SE ITERÁTOR POUŽIVÁ?
Interně se používá v
• for...of loop
• ...spread operator
• Destructuring
• String, Array, Map, Set, etc
• Cokoliv iterable je možné předat do Promise.all() nebo
Array.from()
7. ZPÁTKY KE GENERÁTORŮM
• Generátor je iterátor
• Iterátor je terminátor
• Takže i generátor má metody .next() a .throw()
8. SYNTAXE
• function*()
• *() => {}
• function* myGenerator()
• GENERÁTOR MUSÍ MÍT HVĚZDIČKU
• Kdo má hvězdičku, může používat yield
• yield je možné použít jen uvnitř generátoru.
9. SYNTAXE II.
• Generátor je možné použít i uvnitř class
class MyClass {
* generatorMethod() {
···
}
}
let myInstance = new MyClass();
let genObj = myInstance.generatorMethod();
10. UKAŽ MI KÓD
// THERE IS 4X .NEXT() BUT JUST 3X YIELD
"use strict";
function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
// create instance of an iterator
const it = myGenerator();
console.log(it.next()); // outputs {value: 1, done: false}
console.log(it.next()); // outputs {value: 2, done: false}
console.log(it.next()); // outputs {value: 3, done: false}
console.log(it.next()); // outputs {value: undefined, done: true}
11. PROČ POŘÁD VOLÁŠ .NEXT()?
• Protože generátor jede jen dokud nenarazí na yield, pak se
zastaví a čeká
• Nemůže se sám rozjet, musíme mu pomoct a zavolat .next()
• A na co tedy čeká?
• Čeká na pohádku
12. LEHCE YIELDNUTÁ POHÁDKA
• Žil byl jeden skřítek ve svém domečku z generátoru. Měl v ruce
lísteček s instrukcemi, které má vykonat. Instrukce měl napsané
v javascriptu
• Chodil po domě a vykonával instrukce.
• Vždy když došel v instrukcích na yield, tak vytáhnul ze skříně
balíček, otevřel okno a čekal, až si balíček někdo vezme
• Skřítek čekal, že za balíček něco dostane zpátky
• Když na něj někdo zavolal .next(), sebral z okna to co dostal
místo balíčku, pokud něco dostal a pokračoval v instrukcích
13. VYSVĚTLENÍ YIELDNUTÉ POHÁDKY
• Yield je expression. To znamená, že se vykoná a nahradí se
nějakou hodnotou.
• Je to způsob oboustranné komunikace mezi generátorem a
jeho okolím
• Když pouštím generátor, tak mu můžu předat hodnout jako
parametr v .next()
• Předaná hodnota se pak uloží do proměné v generátoru a je s
ní možné dále pracovat
14. PŘÍKLAD
"use strict";
function* myHouseElf(){
var x = yield "gimme money"; // elf is waiting for money
console.log("I received so much", x);
}
var it = myHouseElf();
var y = it.next();
console.log(y); // y = {value: "gimme money", done: false}
it.next(10); // prints "I received so much, 10"
15. YIELDNUTÁ POHÁDKA Č II.
YIELD *
• V jedné chaloupce žil zlý skřet. Držel v ruce papírek s
instrukcemi v javascriptu a neměl nikoho rád. Nejraději všechnu
svoji práci delegoval na nebohé skřítky.
• Tenhle skřet totiž používal yield *
16. YIELD *
• Způsob jak z jednoho generátoru volat jiný generátor
• Obdoba funkce, která volá jinou funkci, která volá jinou funkci, která volá jinou
funkci, která volá jinou funkci
Pro snažší pochopení:
• Iterátor je sekvence hodnot
• Yield * do této sekvence vloží jinou sekvenci a tím ji prodlouží
• Funkce kt. daný iterátor volá, o tom neví. Myslí si, že iteruje pořád tu
samou kolekci
17. UKAŽ MI KÓD
1. function* caller() {
2. yield 1;
3. yield 2;
4.
5. // here is that star ?
6. const a = yield* callee();
7. console.log(`variable a from callee() is ${a}`);
8.
9. yield 5;
10. }
11.
12. function* callee() {
13. yield 3;
14. yield 4;
15. return 'A from Callee';
16. }
17. for (var v of caller()){
18. console.log(v);
19. }
18. NIKDO NECHCE POŘÁD VOLAT .NEXT(),
.NEXT(), .NEXT(), .NEXT(), .NEXT(), .NEXT(),
.NEXT(), .NEXT()
• Pro to existují různé helper funkce, které berou generátor jako
svůj (jediný) argument
• Spustí ho
• A pohlídají, že všechny yieldy jsou postupně zavolané
19. CO()
Use co() or something like that - https://github.com/tj/co
Počká na všechny yieldy a vrátí Promise.
1. co(function*(){
2. yield 1;
3. yield 2;
4. yield 3;
5. }).then(() => {
6. console.log(“All done”);
7. })
20. EMBER CONCURENCY
• Pokud používáte EmberJs, tak doporučuji vyzkoušet addon
Ember-Concurency
• http://ember-concurrency.com/
• Řeší spoustu problémů, o kterých jste nevěděli, že je máte
• Computed properties: task.isRunning, task.isIdle
• Method: task.perform()
• Proč je EC skvělý? .next() slide please
21. PROČ JE EMBER CONCURENCY SKVĚLÝ?
• Real life example:
• Uživatel na něco klikne a spustí tím řetězovou reakci ajax
requestů, callbacků atd.
• Request ale trvá dlouho, uživatele to přestane bavit a jde na
jiné view. Po chvíli se vrátí.
• Spuštěný ajax request ale pořád jede a všechny callbacky se
později vykonají. To může udělat zmatek v datech, když se vám
smíchají stará a nová data atd. (Controllery v Emberu jsou totiž
singletony)
22. PROČ JE EMBER CONCURENCY SKVĚLÝ? II
• EC je postavený nad generátory.
• Generátory jsou interně implementované jako state-machine
• Když uživatel odejde z view, tak se daná state-machine zahodí
a žádné další requesty, callbacky atd se nevykonají.
• Všechny requesty a callbacky pak mají stejnou životnost jako
objekt, který je zavolal (parent)
• Toho nelze docílit s Promise! Promise není cancellable
23. ASYNC / AWAIT
• Jak už jsme si říkali, nikdo nechce volat .next(), .next(), .next()
pořád dokola
• Máme na to helper funkce, které volají .next() za nás, dokud
nevrátí {done: true}
• Async / await je syntax sugar, který zastupuje tuto helper
funkci
• Boilerplate code v podstatě celý zmizí (viz next slide)
• Viz https://tc39.github.io/ecmascript-asyncawait/#desugaring