Что такое TameJS ?
TameJS — это расширение Javascript, которое делает событийное/асинхронное программирование более простым и элегантным. Его очень просто использовать с nodejs или другими v8-проектами.
Простой пример
Допустим, у нас есть сайт знакомств, и мы хотим написать обработчик посещения пользователем «Angel» страницы пользователя «Buffy».
Алгоритм такого визита следующий:
- высчитать рейтинг(score), насколько Buffy подходит Angel (общие интересы и предпочтения)
- найти следующую пару для Angel
- отметить посещение, записать время визита
- послать Buffy уведомление о посещении, только если — 1) рейтинг сходства высок и 2) пользователи не посещали страницы друг друга
При линейном программировании, код выглядел бы так:
handleVisit : function(angel, buffy) {
var match_score = getScore(angel, buffy);
var next_match = getNextMatch(angel);
var visit_info = recordVisitAndGetInfo(angel, buffy);
if (match_score > 0.9 && ! visit_info.last_visit) {
sendVisitorEmail(angel, buffy);
}
doSomeFinalThings(match_score, next_match, visit_info);
}
Это выглядит наглядно, однако нам необходимо использовать асинхронное программирование, и код становится таким:
handleVisit : function(angel, buffy) {
getScore(angel, buffy, function(match_score) {
getNextMatch(angel, function(next_match) {
recordVisitAndGetInfo(angel, buffy, function(visit_info) {
if (match_score > 0.9 && ! visit_info.last_visit) {
sendVisitorEmail(angel, buffy);
}
doSomeFinalThings(match_score, next_match, visit_info);
});
});
});
}
Теперь код правильный, асинхронный, не содержит блокирующих вызовов, но читать его стало заметно сложнее для, например, стороннего программиста.
Также, мы можем заметить, что в нашем коде вызовы функций getScore, getNextMatch и recordVisitAndGetInfo не зависят друг от друга и могли бы выполняться параллельно.
Чем же нам поможет TameJS?
C TameJS код будет выглядеть следующим образом:
handleVisit : function(angel, buffy) {
await {
getScore (angel, buffy, defer(var score));
getNextMatch (angel, buffy, defer(var next));
recordVisitAndGetInfo (angel, buffy, defer(var vinfo));
}
if (score > 0.9 && ! vinfo.last_visit) {
sendVisitorEmail(angel, buffy);
}
doSomeFinalThings(score, next, vinfo);
}
Код стал наглядным, читаемым, и при этом он полностью асинхронный и выполняется быстрее, чем предыдущий асинхронный вариант за счет параллельного исполнения getScore, getNextMatch и recordVisitAndGetInfo!
Вам понравилось также, как и мне?
Установка TameJS
Установка в Node.JS делается через пакетный менеджер npm:
npm install -g tamejs
И далее в коде регистрируем расширение языка:
require ('tamejs').register (); // register the *.tjs suffix
require ("mylib.tjs"); // then use node.js's import as normal
Вот и все! Далее, Tame сам компилирует tjs файлы в нативный JS.
Как работает TameJS
Синтаксический сахар TameJS заключен всего в двух, совместно используемых, ключевых словах await и defer
var res1, res2;
await {
doOneThing(defer(res1));
andAnother(defer(res2));
}
thenDoSomethingWith(res1, res2);
Блок await помечает секцию кода, содержащую внешние события, например, общение с сетью или работа с диском, или таймер. В блоке await содержится несколько defer. Прохождение блока await завершается только после выполнения всех defer в блоке. defer() возвращает анонимную функцию, которую нужно использовать как callback для асинхронных вызовов. Если ваши callback функции предполагают наличие аргументов, укажите этот набор аргументов в defer(). Эти результаты будут доступны после завершения блока await.
Об авторах
TameJS разработан OkCupid и распространяется по лицензии MIT. Есть репозиторий в github, проект молодой, активность в проекте присутствует.
Сайт проекта — tamejs.org
Альтернативы
Если вас заинтересовали расширения, влияющие на поток команд, рекомендуется обратить внимание также на StratifiedJS, Step и Seq.