Generators

Жигалов Сергей

Generators

Сергей Жигалов

ChellyJS, 2015г

Список неоплаченных штрафов

  1. Ввести номер автомобиля
  2. Получить по номеру автомобиля список штрафов
  3. Получить по каждому штрафу статус оплаты
  4. Вывести неоплаченные штрафы

Callback

        function getUnpaidFines(carNumber, cb) {
            getFinesByCarNumber(carNumber, function (err, fines) {
                if (err) { cb(err); }
                var isUnpaidFines = [];
                var finesCounter = fines.length;
                fines.forEach(function (fine, index) {
                    isFineUnpaid(fine, function (err, isUnpaid) {
                        if (err) { cb(err); }
                        isUnpaidFines[index] = isUnpaid;
                        if (--finesCounter === 0) {
                            var unpaidFines = filterUnpaidFines(fines, isUnpaidFines);
                            cb(null, unpaidFines);
                        }
                    })
                });
            });
        }
    
catIsSad

Callback

        function getUnpaidFines(carNumber, cb) {
            getFinesByCarNumber(carNumber, function (err, fines) {
                if (err) { cb(err); }
                var isUnpaidFines = [];
                var finesCounter = fines.length;
                fines.forEach(function (fine, index) {
                    isFineUnpaid(fine, function (err, isUnpaid) {
                        if (err) { cb(err); }
                        isUnpaidFines[index] = isUnpaid;
                        if (--finesCounter === 0) {
                            var unpaidFines = filterUnpaidFines(fines, isUnpaidFines);
                            cb(null, unpaidFines);
                        }
                    })
                });
            });
        }
    

Callback

        function getUnpaidFines(Ввести номер автомобиля, cb) {
            Получить список штрафов(carNumber, function (err, fines) {
                if (err) { cb(err); }
                var isUnpaidFines = [];
                var finesCounter = fines.length;
                fines.forEach(function (fine, index) {
                    Получить статус оплаты(fine, function (err, isUnpaid) {
                        if (err) { cb(err); }
                        isUnpaidFines[index] = isUnpaid;
                        if (--finesCounter === 0) {
                            var unpaidFines = Вывести неоплаченные штрафы
                            cb(null, unpaidFines);
                        }
                    })
                });
            });
        }
    

Callback

Promises. Bluebird

        function myFunction(arg1, arg2, cb) {
            cb(err, data);
        }
        var myPromisifyFunction = Promise.promisify(myFunction);
         
        myPromise()
            .then(function onResolve() { return data; })
            .then(function onResolve(data) { ... })
            .catch(function onReject() { ... })
         
    
bluebird
https://github.com/petkaantonov/bluebird
Михаил Давыдов "Promise – это не больно"

Promises

        function getUnpaidFines(carNumber) {
            return getFinesByCarNumber(carNumber)
                .then(function (fines) {
                    return Promise.props({
                        fines: fines,
                        isUnpaidFines: Promise.all(fines.map(isFineUnpaid))
                    });
                })
                .then(function (data) {
                    return filterUnpaidFines(data.fines, data.isUnpaidFines);
                });
        }
    

Promises

Мой идеальный код

        function getUnpaidFines(Ввести номер автомобиля) {
            var fines = Получить список штрафов(carNumber);
            var isUnpaidFines = fines.map(Получить статус оплаты);
            return Вывести неоплаченные штрафы(fines, isUnpaidFines);
        };
    

Мой идеальный код

        function getUnpaidFines(carNumber) {
            var fines = getFinesByCarNumber(carNumber);
            var isUnpaidFines = fines.map(isFineUnpaid);
            return filterUnpaidFines(fines, isUnpaidFines);
        }
    

Мой идеальный код. Generator

        function getUnpaidFines(carNumber) {
            var fines = yield getFinesByCarNumber(carNumber);
            var isUnpaidFines = yield fines.map(isFineUnpaid);
            return filterUnpaidFines(fines, isUnpaidFines);
        }
    

Мой идеальный код. Generator

        function *getUnpaidFines(carNumber) {
            var fines = yield getFinesByCarNumber(carNumber);
            var isUnpaidFines = yield fines.map(isFineUnpaid);
            return filterUnpaidFines(fines, isUnpaidFines);
        }
    
catsShock

Мой идеальный код. Generator

        co(function *getUnpaidFines(carNumber) {
            var fines = yield getFinesByCarNumber(carNumber);
            var isUnpaidFines = yield fines.map(isFineUnpaid);
            return filterUnpaidFines(fines, isUnpaidFines);
        }) 
            .then(console.log.bind(console))
            .catch(console.error.bind(console));
    

Generator

A generator can pause itself in mid-execution, and can be resumed either right away or at a later time.

ES6 ES2015

Generator. Declaration

        function *foo(name) {
            console.log('Hello, ' + name);
        }
    

Generator. Execution

        function *foo(name) {
            console.log('Hello, ' + name);
        }
         
        foo('ChellyJS');
    

Console:

            >
        

Generator. Iterator

An iterator is a structured pattern for pulling information from a source in one-at-a-time fashion.
        it.next()
    

Console:

            > { value: {...}, done: false}
        

Generator. Execution

        function *foo(name) {
            console.log('Hello, ' + name);
        }
         
        var it = foo('ChellyJS');
        it.next();
    

Console:

            > Hello, ChellyJS
        

Generator. yield

        function *foo() {
            console.log('1');
            yield;
            console.log('2');
        }
         
        var it = foo();
        it.next();
        // Do somethings...
        it.next();
    

Console:

            >
            > 1
            >
            > 2
        

Generator. yield

        function *foo() {
            yield 'Some data';
        }
         
        var it = foo();
        console.log(it.next());
        console.log(it.next());
    

Console:

            > {value: "Some data", done: false}
            > {value: undefined, done: true}
        

Generator. Аналогия

        function *order() {
            yield 'Цезарь';
            yield 'Окрошка';
            yield 'Шоколадный кексик с мороженкой';
            yield 'Компотик';
        }
         
        var it = order(); // Подходит официант
        it.next(); // " - Что будете заказывать?"
    

Generator. Аналогия

        function *order() {
            yield 'Цезарь';
            yield 'Окрошка';
            yield 'Шоколадный кексик с мороженкой';
            yield 'Компотик';
        }
         
        var it = order(); // Подходит официант
        it.next(); // " - Что будете заказывать?"
        it.next(); // " - Хорошо"
    

Generator. Аналогия

        function *order() {
            yield 'Цезарь';
            yield 'Окрошка';
            yield 'Шоколадный кексик с мороженкой';
            yield 'Компотик';
        }
         
        var it = order(); // Подходит официант
        it.next(); // " - Что будете заказывать?"
        it.next(); // " - Хорошо"
        it.next(); // " - Что нибудь еще?"
    

Generator. Аналогия

        function *order() {
            yield 'Цезарь';
            yield 'Окрошка';
            yield 'Шоколадный кексик с мороженкой';
            yield 'Компотик';
        }
         
        var it = order(); // Подходит официант
        it.next(); // " - Что будете заказывать?"
        it.next(); // " - Хорошо"
        it.next(); // " - Что нибудь еще?"
        it.next(); // " - Пить что будете?"
    

Generator. Аналогия

        function *order() {
            yield 'Цезарь';
            yield 'Окрошка';
            yield 'Шоколадный кексик с мороженкой';
            yield 'Компотик';
        }
         
        var it = order(); // Подходит официант
        it.next(); // " - Что будете заказывать?"
        it.next(); // " - Хорошо"
        it.next(); // " - Что нибудь еще?"
        it.next(); // " - Пить что будете?"
        it.next(); // " - Все"
    

Generator

        co(function *getUnpaidFines(carNumber) {
            var fines = yield getFinesByCarNumber(carNumber);
            var isUnpaidFines = yield fines.map(isFineUnpaid);
            return filterUnpaidFines(fines, isUnpaidFines);
        }) 
            .then(console.log.bind(console))
            .catch(console.error.bind(console));
    

Generator. CO

Generator based control flow goodness for nodejs and the browser, using promises, letting you write non-blocking code in a nice-ish way.
https://github.com/tj/co

        co(function* () {
            var value = yield Promise.resolve(true);
            return value;
        }).then(function (value) {
            console.log(value); // true
        });
    

Generator

Generator. Поддержка

Generator. Babel

https://babeljs.io/
babel

Альтернативные фреймворки

Ссылки

Спасибо за внимание!

mailzhigalov@yandex-team.ru
twitter@sergey_zhigalov