Статьи

Введение в Generators & Koa.js: Часть 1

Koa.js — это выразительная веб-инфраструктура следующего поколения, написанная для Node.js людьми, работающими над платформами Express и Connect. Koa.js использует генераторы, которые являются передовой особенностью JavaScript и еще не были превращены в стабильные версии Node.js. Koa стремится использовать генераторы, чтобы избавить разработчиков от спагетти обратных вызовов, делая его менее подверженным ошибкам и, следовательно, более управляемым.

Koa — всего 550 строк кода — чрезвычайно легкая структура. Даже после этого Koa упаковывает в элегантный набор методов, таких как согласование содержимого, перенаправления, поддержка прокси и т. Д., Обеспечивая простоту и скорость разработки, а также детальный контроль над приложением вашего узла.

Теперь, прежде чем мы начнем, вам понадобится как минимум Node версии 0.11.x или выше.

Вы можете установить последнюю версию Node, используя модуль N:

1
2
sudo npm install -gn
sudo n stable

Вы также можете использовать другие модули сообщества, такие как nvm или создать его из исходного кода. Обратите внимание, что N также является модулем сообщества.


Чтобы запустить файл JS, в котором используются генераторы, вам необходимо --harmony флаг --harmony при его запуске.

Например, чтобы запустить app.js , введите следующую команду:

1
node —harmony app.js

Или чтобы не вводить этот флаг каждый раз, вы можете создать псевдоним с помощью следующей команды:

1
alias node=»node —harmony»

Теперь, чтобы запустить ваше приложение с помощью генераторов, просто введите:

1
node app.js

Очень хорошо! Также имейте в виду, что весь код этой статьи доступен на GitHub . Не стесняйтесь раскошелиться и поиграть с ним.

Теперь, чтобы понять Коа, вы должны сначала понять генераторы, которые формируют позвоночник каркаса.


С ES-6 генераторы наконец-то приземлились в волшебной стране JavaScript. Если у вас есть опыт работы с генераторами в Lua, Python, Scheme, Smalltalk и т. Д., То вам будет приятно узнать, что в JavaScript реализована очень похожая вещь.

Генераторы — это первоклассные сопрограммы в JavaScript, которые, проще говоря, вводят интерфейс паузы и воспроизведения в языке. До генераторов весь скрипт обычно выполнялся в порядке сверху вниз, без простого способа остановить выполнение кода и возобновить работу с тем же стеком позже. Теперь давайте запачкаем руки примерами.

В соответствии с текущим проектом спецификации ES-6 нам нужно использовать другую версию определения функции для создания функции генератора. Это выглядит так:

1
var generator_func = function* () { };

Здесь generator_func — это просто пустая функция генератора.


Поэтому мы можем использовать ключевое слово yield в функции, чтобы остановить выполнение и сохранить текущий стек.


Вот простой пример, демонстрирующий сумму бесконечного AP:

01
02
03
04
05
06
07
08
09
10
11
12
13
var r = 3;
 
function* infinite_ap(a) {
     for( ; ; ) {
        a = a + r;
        yield a;
      }
}
 
var sum = infinite_ap(5);
 
console.log(sum.next());
console.log(sum.next());


В приведенном выше коде мы изначально создаем экземпляр итератора с именем infinite_ap который включает в себя бесконечный цикл и, если он выполняется в нормальных условиях, может заморозить выполнение.

Далее мы сохраняем экземпляр итератора в переменной sum .

Теперь, когда мы вызываем sum.next() , он возвращает { value: 8, done: false } что означает, что он остановил свое выполнение в операторе yield возвращающем value как «a» и done как «false».

Здесь done возвращает false, пока выполнение не будет завершено. Когда выполнение завершено (в вышеупомянутом случае это никогда не происходит), функция возвращает {value: undefined, done: true} .

Вот небольшая модификация предыдущего кода, чтобы продемонстрировать конец выполнения:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var r = 3;
 
function* infinite_ap(a) {
    for( var i = 0; i < 3 ; i++) {
       a = a + r ;
       yield a;
    }
}
 
var sum = infinite_ap(5);
 
console.log(sum.next());
console.log(sum.next());
console.log(sum.next());
console.log(sum.next());


В более сложных программах вы должны проверять и использовать возвращаемые значения и состояние « done .


Примечание : использование yield без function* приведет к ранней ошибке.



Вот несколько распространенных методов, которые пригодятся вам при работе с ванильными генераторами.

Каждый из методов ниже доступен только в функции генератора и в противном случае выдает ошибку.


Это используется для возобновления выполнения вместе с передачей аргумента. Если ничего не передано, то undefined передается в качестве первого аргумента.

Пример: sum.next(5);



Это используется, чтобы вызвать ошибку или исключение на любом этапе. Это делает обработку ошибок намного проще. Выдача ошибки может привести к остановке выполнения файла, если он где-то не обрабатывается. Самый простой способ обработки ошибки — использовать оператор try и catch. Этот метод принимает один аргумент, который может быть чем угодно.

Пример: sum.throw(new Error("this is an error"));



Делегирование генератора используется для получения генератора из существующего генератора и может использоваться для создания генераторов или даже итерации по генератору.

При делегировании другому генератору генератор тока прекращает производить само значение и начинает давать значения делегированного генератора, пока он не будет исчерпан. После исчерпания делегированного генератора генератор возобновляет возврат своего собственного значения.

Это очень похоже на использование цикла for-in над генератором, но исключения делегированного генератора распространяются и генерируются с помощью метода throw внешнего генератора и должны обрабатываться аналогичным образом. Вот пример:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var consoleLogThunk = function(msg) {
    return function() {
        console.log(msg);
      }
}
 
var generator = function*() {
    yield consoleLogThunk(«Yo»);
    yield consoleLogThunk(«Dawg»);
    yield consoleLogThunk(«!!!»);
}
 
var delegator_function = function* () {
    yield consoleLogThunk(«I yielded before delegated yield»);
    yield* generator();
    yield consoleLogThunk(«I yielded after delegated yield»);
}
 
var k = delegator_function();
 
k.next().value();
k.next().value();
k.next().value();
 
console.log(k.next());

Теперь, когда у вас есть краткое представление о генераторах в Javascript, вы можете использовать их для написания гораздо более понятных и менее подверженных ошибкам приложений, в которых вы можете блокировать ввод-вывод, фактически не блокируя процесс.

Давайте теперь перейдем к установке Koa и очень простого приложения на основе Koa.js.


Koa — это объект, который содержит массив функций генератора промежуточного программного обеспечения, все из которых составляются и выполняются стековым способом при каждом запросе.

В каталоге вашего проекта выполните следующую команду.

1
npm install koa —save

Koa будет автоматически загружен и сохранен в файле package.json , если он существует.

Несмотря на то, что Koa занимает очень мало места, он включает методы для таких задач, как обновление кэша, согласование контента, перенаправления, поддержка прокси и т. Д., Без промежуточного программного обеспечения.

Вот пример приложения hello-world:

1
2
3
4
5
6
7
8
var koa = require(‘koa’);
var app = koa();
 
app.use(function *(){
    this.body = «Hello World !!!»;
});
 
app.listen(3000);

Теперь Коа также осуществляет нисходящий поток с последующим восходящим потоком управления. Сначала это может быть трудно задыхаться, но как только вы пройдете через пример ниже, все станет яснее.

Вот пример потока управления в Коа:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var koa = require(‘koa’)();
 
koa.use(function* (next) {
    //do something before yielding/passing to next generator function in line which will be 1st event in downstream
    console.log(«A»);
    yield next;
 
    // do something when the execution returns upstream, this will be last event in upstream
    console.log(«B»);
});
 
koa.use(function* (next) {
    // do something before yielding/passing to the next generator function in line, this shall be 2nd event downstream
    console.log(«C»);
 
    yield next;
 
    // do something when the execution returns upstream and this would be 2nd event upstream
    console.log(«D»);
});
 
koa.use(function* () { // do something before yielding/passing to next generator function in line. Here it would be last function downstream
    console.log(«E»);
    this.body = «hey guys»;
    console.log(«F»);
 
});
 
koa.listen(3000);

Код выше довольно прост. Обратите внимание, что не все операторы console.log являются обязательными, но они помогут вам четко понять нисходящий и восходящий поток выполнения Koa.js.

Когда мы запускаем это приложение и открываем localhost:3000 в браузере, мы видим, что console.logs в терминале не в порядке ABCDEF . И при этом они не в порядке ACEBDF .

Порядок на самом деле ACEFDB, который отображает нисходящий поток и восходящий поток выполнения в приложении Koa.

Вы можете заметить, что он напечатан дважды. Это связано с двойным запросом, отправленным браузером для получения значка.

Совет : koa.use(function) добавляет функцию промежуточного программного обеспечения в приложение.


Вот и все для первой части этого учебника по генераторам JavaScript и Koa.js. Вы узнали о большинстве предпосылок, таких как генераторы, как их использовать, как использовать делегирование yield и как работает поток управления в Koa.js.

В следующей части этого руководства мы углубимся в Koa и узнаем, как создать приложение CRUD. Если у вас есть какие-либо вопросы или комментарии, не стесняйтесь связаться со мной или просто оставьте комментарий ниже.