- PVSM.RU - https://www.pvsm.ru -
Когда мы начинаем разбираться с ES6, генераторы находятся чуть ли не в конце списка нововведений, на которые мы обращаем внимание. Зачастую мы просто воспринимаем генераторы как простой способ создания кастомных итераторов, но на самом деле они могут предоставить нам намного более интересные возможности и скорее всего являются одним из самых интересных нововведений в ES6.
Генераторы — это функции которые можно запустить, приостановить и возобновить на различных стадиях выполнения. По сути дела, эта специальная функция возвращает итератор. Функции генераторы обозначаются звездочкой после ключевого слова function, а вся магия спрятана в использовании специального ключевого слова yield. Оно определяет, что итератор должен вернуть после очередного вызова метода next().
И сразу же пример простого генератора в ES6:
function* myGenerator() {
yield ‘first’;
let input = yield ‘second’;
yield input;
}
// Получаем объект генератора
let iterator = myGenerator();
// Запускаем генератор, доходим до первого yield
console.log(iterator.next()): // { value: ‘first’, done: false }
// Возобновляем(не передаем никакого значения), доходим до второго yield
console.log(iterator.next()); // { value: ‘second’, done: false }
// Возобновляем (передаем значение) доходим до последнего yield
console.log(iterator.next(‘third’)); // { value: ‘third’, done: false }
// Заканчивается работа (yield больше нет)
console.log(iterator.next()); // { value: undefined, done: true }
Итак, что же здесь происходит?
В начале статьи было упомянуто, что зачастую генераторы используются как простой механизм создания итераторов. Все это можно сделать используя синтаксис for of:
Например:
function* myGenerator() {
yield ‘first’;
yield ‘second’;
yield ‘third’;
}
for (var v of myGenerator()) {
console.log(v);
}
Или например:
function* myGenerator(start, stop) {
for (var i = start; i < stop; i++)
yield i;
}
for (var v of myGenerator()) {
console.log(v);
}
Ладно, итераторы это здорово, но давайте посмотрим какие вещи покруче можно сделать используя генераторы.
Итак, нам нужно залогиниться на какой то бекенд, затем использовать токен аутентификации для того, чтобы извлекать данные из API. Если применить механизм генераторов это будет выглядеть так:
co(function* () {
var result = yield login(username, password);
var posts = yield getPosts(result.token);
return posts;
}).then(value => {
console.log(value);
}, err => {
console.error(err);
});
function login(username, password) {
return fetch(‘/login’, {
method: ‘post’,
body: JSON.stringify({
username: username
password: password
})
}).then(response => response.json());
}
function getPosts(token) {
return fetch(‘/posts’, {
headers: new Headers({
‘X-Security-Token’: token
})
}).then(response => response.json());
}
В этом примере используется библиотека co [1], которая делает ваш асинхронный код похожим на синхронный используя механизм промисов. Здесь для каждого yield промис возвращает результат в функцию генератор и сохраняет в переменную.
Эээээ, Koa? Это что вообще такое?
Koa — это фреймворк нового поколения(из подзаголовка официального сайта), который улучшает механизм написания middleware, используя как раз таки генераторы и библиотеку co [1], и избавляя таким образом ваше приложения от ада из коллбеков [2].
С философской точки зрения, Koa стремится “исправить и заменить node”, а Express наоборот, “расширить node”(из документации Koa).
Middleware в Koa построены на механизме генераторов и представляют собой “каскад”. Проще говоря, сначала запускается механизм “вниз по течению”(downstream) через все middleware, а после этого “вверх по течению” через все middleware(upstream).
Итак, пример:
var koa = require('koa');
var app = koa();
// x-response-time
app.use(function *(next){
var start = new Date;
yield next;
var ms = new Date - start;
this.set('X-Response-Time', ms + 'ms');
});
// logger
app.use(function *(next){
var start = new Date;
yield next;
var ms = new Date - start;
console.log('%s %s - %s', this.method, this.url, ms);
});
// response
app.use(function *(){
this.body = 'Hello World';
});
app.listen(3000);
Этот пример вернет нам 'Hello World', однако сперва:
Круто в общем, что еще сказать. Подробнее про Koa можно посмотреть на официальном сайте [3] и на гитхабе [4].
Генераторы в ES6 представляют собой мощный механизм, который дает возможность писать более чистый и понятный асинхронный код. Вместо того, чтобы использовать ворох коллбеков по всему коду мы можем теперь писать асинхронный код, который с виду похож на синхронный, но на самом деле при помощи генераторов и ключевого слова yield “поджидает” завершения асинхронной операции.
Автор: Good_Karma
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/111979
Ссылки в тексте:
[1] co: https://github.com/tj/co
[2] ада из коллбеков: http://callbackhell.com/
[3] официальном сайте: http://koajs.com/
[4] гитхабе: https://github.com/koajs/koa
[5] Источник: https://habrahabr.ru/post/277033/
Нажмите здесь для печати.