ANDRII DATSENKO <ASDatsenko@luxoft.com>

SOFTWARE ENGINEER

March 15, 2017

GENERATORS*
ESSENTIALS

 PLAIN ASYNC CODE

Generators are functions which can be exited and later re-entered

PURPOSE*

iterate

async

lazy

delegation

PAUSE

function* logger() {
  console.log('Start');
  yield;
  console.log('End')
}

const it = logger();

it.next(); // 'Start'
it.next(); // 'End'

GET VALUES

function* random() {
  yield Math.random();
  yield Math.random();
}

const it = random();

it.next().value; // 0.47837466700776021
it.next().value; // 0.17492062465918323
it.next().done; // true

PASS VALUES

function* greeting() {
  const name = yield;
  yield `Hello ${name}!`;
}

const it = greeting();

it.next();
it.next('Andrew').value; 
// 'Hello Andrew!'

ERRORS

function* fail() {
  try {
    const result = yield;
    console.log(result);
  } catch(e) {
    console.error(e);
  }
}

const it = fail();

it.throw(new Error('Fail happened'));

ERRORS

function* fail() {
  const result = yield 1;
  throw new Error('Oops');
}

const it = fail();

try {
  it.next();
  it.next();
} catch(e) {
  console.error(e);
}

ITERATOR

var data = {b:2, a:1};
data[Symbol.iterator] = function*() {
    const props = Object.keys(this).sort();
    for (let a of props) {
         yield a;
    }
}

[...data]; // ['a', 'b']

for(let key of data) {
    console.log(key);
}

ITERATOR

function* range(min, max) {
    while(min < max) {
        yield min++;
    }
}

for(let val of range(20,30)) {
    console.log(val)
}

const arr = [...range(0, 100)];

API REQUEST

function* fetchUserCompany() {
    const userFetch = yield fetch('/me');
    const {companyId} = yield userFetch.json();
    const companyFetch = yield fetch(`/company/${companyId}`);
    return yield companyFetch.json();    
}

const it = fetchUserCompany();

it.next().value
    .then((userJson) => it.next(userJson).value)
    .then((companyJson) => it.next(companyJson).value)
    .then((company) => console.log(company))

API REQUEST (CO)

import * as co from 'co';

function* fetchUserCompany() {
    const userFetch = yield fetch('/me');
    const {companyId} = yield userFetch.json();
    const companyFetch = yield fetch(`/company/${companyId}`);
    return yield companyFetch.json();    
}

co(getUserCompany())
    .then((company) => {
        console.log(company)
    });

DELEGATION

function* oneTwo() {
    yield 1;
    yield 2;
}

function* eightNine() {
    yield 8;
    yield 9;
}

function* dozen() {
    yield 0;
    yield* oneTwo();
    yield* [3, 4, 5, 6, 7];
    yield* eightNine();
}

[...dozen()];
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

DELEGATION

import * as co from 'co';

function* fetchUser() {
    const userFetch = yield fetch('/me');
    return yield userFetch.json();
}

function* fetchUserCompany() {
    const {companyId} = yield* fetchUser();
    const companyFetch = yield fetch(`/company/${companyId}`);
    return yield companyFetch.json();    
}

co(fecthUserCompany)
    .then(company => console.log(company));

LAZY EVALUATION

function* random() {
    while(true) yield Math.random();
}

function* filter(items, predicate) {
    for(let item of items) {
        if(predicate(item)) yield item;
    }
}

function* take(items, number) {
    let count = 0;

    for(let item of items) {
        yield item;
        if(++count >= number) return;
    }
}

const items = [...take(filter(random(), n => n < 0.5), 2)];
// [0.04971046381666788, 0.3152250891138142]

LINKS

Q&A Time

ANDRII DATSENKO <ASDatsenko@luxoft.com>

SOFTWARE ENGINEER

 

March 15, 2017

GENERATORS*
ESSENTIALS

 PLAIN ASYNC CODE

JS Generators Essentials

By Andrew Dacenko

JS Generators Essentials

  • 1,027