Node.js і JavaScript замість старого веба

Вступ
Ця стаття про експериментальний технологічний стек загального призначення. Вона не просто дублює моя доповідь на конференції ОдессаЈЅ 2016, але містить все те, що доповідь не помістилося з-за браку часу і виняткового масштабу теми. Я навіть перезаписав доповідь голосом по тексту статті і це можна послухати, а не читати. З цією темою я вже виступив Уханьском Університеті (Китай), а в Київському Політехнічному Інституті провів цілу серію семінарів в 2015-2016 роках. Основна ідея полягає в тому, що проблеми фрагментації технологій можуть бути вирішені, якщо спроектувати весь технологічний стек, сконцентрувавшись на структурах даних, синтаксисі та в протоколі взаємодії компонентів. Більшість питань несумісності, відпаде саме собою. Нехай навіть цей підхід буде альтернативним і експериментальним, але його завдання буде виконано, якщо він визначить шлях і продемонструє принципову можливість створення простого й елегантного рішення загального призначення. Ця ідея є природним продовженням підходу Node.js, коли ми скорочуємо кількість мов і технологій в системі, розробляючи і клієнт і сервер на JavaScript. Незважаючи на експериментальність, протокол JSTP вже використовується в комерційних продуктах, наприклад, для інтерактивного телебачення компанією SinceTV, де дозволяє підключити одночасно десятки мільйонів користувачів. Це рішення отримало приз за інновації в галузі телебачення на міжнародному конкурсі Golden Panda Awards 2015 в Ченду (Китай). Є запровадження у сфері управління серверними кластерами, готуються рішення для медицини, інтерактивних ігор, електронної торгівлі та послуг.
Слайди / Аудіо версія

Виступ
Добрий день, мене звати Тимур Шемседінов, я архітектор SinceTV, автор Impress Application Server Node.js, науковий співробітник НДІ Системних Технологій і викладач КПІ. Сьогоднішня тема не стільки про ноду, а радше про розвиток тієї ідеї, яка лягла в основу ноди.
Кожен, хто розробляв програми не тільки для вебу, може легко порівняти стрункість технологічного стека, обсяги виникаючих проблем і, в кінцевому рахунку, швидкість розробки, з аналогічними по складності проектами для мобільних пристроїв або віконних додатків для десктопів, для суперкомьпьютеров або вбудованої техніки, програмування для серверів і промислової автоматизації обробки даних або іншими галузями застосування програмування.
Кожен крок в вебі — це боротьба, кожна хвилина — біль, кожна строчка — компроміс або латка. В інтернеті безліч статей про те, що хаос заполонив старий веб і хороші фахівці витрачають тижня на найпростіші задачі, як то — посунути кнопочку на 3 пікселя вгору або зловити блукаючий баг в зоопарку браузерів. Наприклад стаття з Медіума «I'm a web developer and i've been stuck with the simplest app for the last 10 days» перекладена на Хабре «Я веб-розробник і вже 10 днів не можу написати найпростіше додаток».
У чому ж проблема? Як ми можемо її виявити і усвідомити? Є інші шляхи? І чи ми можемо рухатися еволюційно, а не революційно, вирішуючи проблеми частинами? Про це і піде мова далі, і в цілій серії доповідей і статей, які я готую і весь наш колектив, і до обговорення яких я Вас запрошую.
Старий веб дійсно поринув у стан, в якому всі рішення тимчасові, немає нічого стабільного і живе без виправлень більше року. Якщо просто залишити систему без змін, то вона швидко прийде в непридатність. Це відбувається із-за безлічі залежностей, які розроблялися в різний час і різними людьми, ніколи не предполагавшими, що ці програмні модулі будуть використовуватися разом. Все в старому вебі створювалося випадково, без єдиного плану, а слідувати стандартам не збираються доже їх автори. Це глобальна фрагментація технологій, інакше і бути не могло, але зараз ми вже бачимо помилки проектування, приклади успіху і аналоги у поза веба, і я хочу запропонувати досить простий шлях вирішення. Цей шлях не зламає всю Вашу життя, але все ж досить радикальний, щоб бути сприйнятим без потрясінь.
Уявіть, що ми відмовимося від HTTP, HTML, CSS, DOM, URL, XMLHttpRequest, AJAX, JSON, JSONP, XML, REST, Server-Sent Events, CORS, Cookie, MIME, WebSocket, localStorage, indexedDB, WebSQL, і всього іншого, крім однієї речі, ми залишимо JavaScript і зробимо з нього абсолютно все, що необхідно для розробки додатків. На перший погляд це може здатися дивним, але далі я покажу, як ми це зробимо. Це буде цілісний технологічний стек на одному лише JavaScript і вам це сподобається. Ми звичайно будемо залучати інші технології для створення середовища виконання додатків, але від розробника додатків всі ці нутрощі будуть приховані.
Отже, почнемо проектувати експериментальний технологічний стек з того, що окреслимо широке коло його застосування, який і визначить набір технологій і вимоги до них. Ми розглянемо загальноприйняті шляхи реалізації та виявимо їх критичні недоліки, після чого подумаємо над можливими варіантами заміни.
Ми хочемо розробляти прикладне програмне забезпечення для інформаційних систем у таких сферах: бізнес, економіка, освіта, медицина, корпоративні інформаційні системи та організаційно-управлінські системи, електронна торгівля, особиста та групова комунікація, соціальні мережі, ігрові програми, телебачення та інші засоби масової інформації.
Ці системи повинні бути:
  • розподіленими (включають в себе багато клієнтських термінальних пристроїв і багато серверів),
  • високонавантаженими (потенційно масштабованими для роботи з мільярдами одночасно підключених пристроїв),
  • інтерактивними (підтримуючими двосторонню інтерактивність, наближену до реального часу),
  • безпечними (одночасно анонімними і забезпечують достатній рівень ідентифікації та довіри для окремих операцій),
  • гнучко змінюються (модифікуючими екрани, функції та структури даних «на льоту», без перевстановлення і перезапуску).
За допомогою яких технологій ми можемо сьогодні розробляти такі програми, перерахуємо:
  • віконні і локально встановлені програми (для Linux, MacOS, Windows) з використанням AWT, SWING, WinForms, WPF, Qt і т. д.
  • мобільні додатки (iOS, Android, і інші)
  • веб-додатки, у тому числі і адаптовані для мобільних версій браузерів
  • Progressive Web App (повноекранні додатки запускаються в прихованому браузері)
  • NW.js і Electron
Іншими словами, одне і те ж додаток доводиться реалізовувати кілька разів на різному технологічному стеку, для різних операційних систем і мобільних платформ. Один і той же інтерфейс, одні і ті ж функції потрібно не тільки реалізувати кілька разів, але і вносити зміни синхронно, підтримуючи всі клієнтські програми в актуальному стані. Для веба ж навпаки, один додаток, але воно тягне за собою кишеньковий браузер з усім його стеком технологій, протоколами, рендерером і проблемами.
Веб міг би бути рішенням для кросплатформенности, але якийсь набір технологій ми маємо в старому вебі:
Почнемо з HTTP. Думаю, ні для кого не секрет, що він блокує, тобто через одне з'єднання, яке браузер встановив, може бути одночасно відправлений тільки один запит на сервер і з'єднання чекає, поки сервер відповість. Тому, що в HTTP немає нумерації запитів, просто звичайної, примітивної, найпростішою нумерації немає і відкрите з'єднання чекає. Адже якщо послати другий запит, отримавши відповідь, буде не ясно, це відповідь на перший запит або на другий. Не кажучи вже про передачу відповіді частинами, які змішалися б. Але при завантаженні програми потрібно зробити багато запитів і браузер встановлює друге з'єднання для другого запиту, потім третю… В більшості браузерів це кількість обмежена 6 одночасними сполуками, тобто зробити більше паралельних запитів не можна, ні для завантаження статики, ні для AJAX. Якщо звичайно не спорудити милицю, створити безліч піддоменів і розкидати запити на піддомени, адже обмеження на 6 сполук у браузера прив'язане саме до хосту. Але ці десятки і сотні сполук неефективно використовують мережу.
Взагалі TCP передбачає надійну доставку та довгострокову взаємодію, але HTTP розриває зв'язок дуже часто, він просто не вміє ефективно переиспользовать вже встановлені з'єднання і постійно розриває їх і створює нові. Є звичайно Keep Alive, але мало того, щоб він був специфицирован, його повинні підтримувати веб-сервер, браузер, і розробники повинні про нього знати, правильно формувати заголовки і обробляти їх. Зазвичай чогось не вистачає, то адмін без руки, то розробники не чули про таку можливість, так і браузери мають особливості, як виявилося, і Keep Alive працює не дуже ефективно, із-за відходу від специфікації сервер часто не може домовитися з браузером і з'єднання не переходить у Keep Alive режим. Я про це вже робив доповідь і писав статтю рік тому "Як виправити помилку у Node.js і ненавмисно підняти продуктивність в 2 рази" Поведінка HTTP можна простежити в засобах для розробника, які є в браузері. Оптимізація HTTP це окрема задача, з коробки її немає і всім байдуже.
Встановлення TCP з'єднання це важка задача, вона довше, ніж передача інформації по вже відкритого сокету. А в добавок до TCP, при встановленні нових сполук HTTP повторно надсилає заголовки, в тому числі cookie. А ми знаємо, що заголовки HTTP не туляться gzip, разом з cookie у великих проектах ходять десятки і сотні кілобайт заголовків. Кожного разу, а у безтурботних людей ще і статика вся гетается з відправкою cookie в кожному запиті. Всім байдуже.
HTTP дуже багато проблем, їх намагалися вирішувати за допомогою Websocket, SSE, SPDY, HTTP/2, QUIC але всі вони залежать від незліченної безлічі речей, які дісталися у спадок від старого веба і жодна з цих технологій не досягла ні прийнятних характеристик, ні широкої підтримки. Ущільнити вже наявний трафік, зробити мультиплексацию всередині іншого транспорту можна, але структура трафіку не зміниться, це будуть всі ті ж HTML, AJAX, JSON, адже завдання стояло, полагодити транспорт так, щоб нічого не зламалося і через нього продовжували ходити все ті ж програми. А от не досягнута мета, все складно, не впроваджується це масово і приріст в швидкості не дуже відчутний при впровадженні. Кардинально і комплексно ні хто не пробував вирішити проблему.
Для ігор, месенджерів та інших інтерактивних додатків зараз є тільки один живий варіант — це Websocket, але цей листковий пиріг з протоколів досяг межі. IP пакетний, на його основі TCP потоковий з встановленням довгих сполук, зверху HTTP — він знову пакетний з постійним відключенням і поверху Websocket — і він потоковий, з довгими сполуками. А ще все це через SSL може йти. І кожен шар додає свої заголовки та перетворює дані, особливо при переході від пакетного до потокового і від потокового до пакетному. Це схоже на знущання, чесне слово.
ігри та месенджери часто не мають достатньої інтерактивності, воно подглючивают, немає потрібної чуйності в доставці, багато накладних витрат і затримок, так і пропускної спроможності потрібної домогтися не так просто. Ось інтерактивні програми і загрузли в розвитку, особливо завдяки тому, що ні в широкому доступі хороших засобів прозорого масштабування вебсокетов на десятки мільйонів одночасних з'єднань. Кожен, кому потрібно вийти за межі десятків тисяч з'єднань, вже робить це для себе сам, хорошого рецепту немає.
Пора визнати, що HTTP, сповнений проблем та милиць, він спроектований напівграмотними в ІТ фізиками CERNа, які не полізли в свою спеціальність, в минулому столітті для передачі статей, забезпечених посиланнями, і ні як не підходить для додатків, тим більше для інтерактивних додатків з інтенсивним обміном даними.
HTML це звичайно прекрасний мову для розмітки сторінок, але менше всього пристосований для складних графічних користувацьких інтерфейсів. Швидкість роботи DOM і відсутність транзакционности у зміні інтерфейсів призводять до залипання веб-додатків. Складно придумати щось більш надмірне і повільне для подання користувальницьких інтерфейсів в пам'яті та динамічної модифікації екранів. Це вирішується в Shadow DOM, React, Angular, Web components але проблем ще більше, ніж рішень.
Ще трохи про масштабування. REST, який обіцяв всім прозоре рішення, замість цього забрав можливість працювати з станом, та не зробив обіцяного. Ми маємо ситуацію, коли ні хто не використовує REST, да ладно, мало хто розуміє, що це, але всі кажуть, що у них REST API. Url ідентифікують об'єкти або методи? PUT, PATCH і DELETE використовуються? Послідовність викликів API не важлива? У кого через REST працюють платежі, кошик, чат, нагадування? В основному у всіх AJAX API, яке так і потрібно називати. А проблема з масштабування як була, так і вирішується кожен раз заново.
Проблем занадто багато для того, щоб вдаватися далі в подробиці, давайте коротким списком тепер підсумуємо основні:
  • Платформи для прикладних програмних систем фрагментовані
  • Архаїчні веб технології вже нас не задовольняють
  • Фреймворки та інструменти тотально нестабільні і несумісні
  • Протоколи старого веба мають велику надмірність і вбивають продуктивність ваших серверів
  • Суцільні проблеми безпеки і латочки
В результаті наше швидко застаріває, ми отримуємо постійні проблеми з інтеграцією систем. Ми не маємо можливості використовувати наші напрацювання, переиспользование коду вкрай ускладнено, ми приречені на сізіфову працю, постійно переробляти одне і те ж.
Що ж нам потрібно:
  • Середовище виконання додатків для серверів
  • Середовище виконання додатків для користувача комп'ютерів
  • Середовище виконання додатків для мобільних пристроїв
  • Межпроцессовое взаємодія за принципами RPC і MQ з підтримкою інтроспекції, потоків подій і потокової передачі двійкових даних
  • Система управління базами даних з глобальним простором адресації, розподіленністю і шардингом з коробки
  • Нові угоди по іменування та ідентифікації даних і користувачів
Це вже не мережу веб-сторінок, а мережа додатків і баз даних.
І тепер я покажу, що це можливо. Не стверджую, що потрібно робити саме так, але принципову можливість на прототипі наша команда продемонструє.
Metarhia — це новий технологічний стек, який:
  • експериментальний (тільки для демонстрації нового підходу),
  • альтернативний (не повинен піклуватися про сумісність),
  • у відкритому коді (можна вільно поширювати і безкоштовно застосовувати навіть в комерційних проектах, участі в розробці та надсилати запити на доопрацювання в співтовариство).
Тепер давайте ближче до JavaScript, в нього ж є прекрасний синтаксис опису структур даних, що включає хеши, масиви, скалярні величини, функції і вирази. А нам потрібен універсальний мережевий протокол, який би відповідав структур даних мови і виключав би зайву перепакування даних. Нам потрібен наскрізний протокол і він же формат серіалізації, один на весь стек технологій, у базі даних, в пам'яті клієнта, в пам'яті сервера і при передачі між процесами. Так навіщо ж нам JSON, XML, YAML та інші, якщо таким форматом може бути підмножиною мови JavaScript. При цьому ми не вигадуємо ні якогось стандарту, який формальної граматики, у нас вже є все. За великим рахунком, заготовки для парсерів вже реалізовані на всіх мовах і платформах. Більш того, якщо ми візьмемо V8 і змусимо його бути парсером мережевих пакетів, то отримаємо статистичну оптимізацію, приховані класи і на порядок більш швидкий парсинг, ніж JSON. Тести продуктивності я опублікую пізніше, щоб не перевантажувати цей, так і об'ємний, доповідь.
Нехай протокол стане центральним стрижнем, на який чіпляються всі компоненти системи. Але протоколу мало, нам потрібна середовище запуску, як клієнтську, так і серверну. Розвиваючи ідеї Node.js ми хочемо, щоб не тільки мову, але й середовище запуску була майже ідентичною на сервері, і на клієнті. Однакове API, яке дає можливість звертатися до функцій платформи, наприклад до мережі, файлової системи, пристроїв введення/виводу. Звичайно ж, це API не повинно бути безконтрольно доступним додатками, а зобов'язана мати обмеження безпеки. Область пам'яті і файлова система повинні бути віртуальними, замкнутими пісочницями, що не мають сполучення з рештою середовищем запуску. Всі бібліотеки мають подгружаться не самими програмами, а впроваджуватися середовищем запуску як DI через інверсію управління (IOC). Права додатків повинні бути контрольовані, але не повинна відбуватися ескалація управління до користувача, тому, що він не здатний прийняти адекватного рішення з прав доступу. Користувач схильний або забороняти все, керуючись параноєю або дозволяти все, керуючись безпечністю.
нам потрібна СУБД, яка буде зберігати дані в тому ж форматі JavaScript. Нам потрібен мова опису моделей (або схем) даних. Нам потрібен мова запитів до структур даних. Як синтаксису цих двох мов запитів ми можемо взяти той же синтаксис JavaScript. І врешті-решт нам потрібен мова опису інтерфейсів двох видів, мережевих інтерфейсів API і користувальницьких інтерфейсів GUI. Підмножина того ж JavaScript чудово нам підходить для обох цілей.
Тепер можемо перерахувати компоненти технологічного стека Metarhia:
  • JSTP — JavaScript Transfer Protocol
  • Impress Application Server — сервер додатків, серверна середовище виконання
  • GS — Global Storage — глобально розподілена система керування базами даних
  • Console — браузер додатків, тонкий клієнт або середовище виконання додатків
JavaScript Transfer Protocol це не тільки формат представлення даних, але і протокол, який має спеціальні конструкції, заголовки, пакети, роздільники, загалом, все те, що забезпечує реалізацію прозорого для додатків взаємодії з мережі. JSTP об'єднує клієнтську і серверну частину так, що вони стають одним цільним додатком. Можна розшарювати інтерфейси і робити виклики функцій абсолютно так само, як якщо б функції знаходилися локально. З єдиним обмеженням, що локально функції можуть бути синхронні та асинхронні, а расшаренные по мережі функції завжди асинхронні, тобто повертають дані не через return, а через callback, який приймають останнім аргументом, як це прийнято в JavaScript. Так само JSTP підтримує трансляцію подій по мережі, обгорнуту в мережній аналог EventEmitter. У JSTP багато можливостей, але зараз наведу лише основні його особливості та переваги:
  • Вбудована підтримка інтерактивності (підтримка подійно-орієнтованого взаємодії),
  • Простий і зрозумілий всім відомий формат (не потрібно вигадувати ще одного стандарту серіалізації),
  • Асинхронність викликів (не блокує принцип використання одного з'єднання з мультиплексацией),
  • Двостороннє взаємодія, максимально наближений до реального часу,
  • Реактивний принцип взаємодії (код реактивному стилі може бути розподіленим),
  • Оптимізація парсинга мережевих пакетів за допомогою механізму прихованих класів V8,
  • Використанням метаданих, моделей (схем даних), інтроспекції та скаффолдинга.
Тепер докладніше про останньому пункті. Метадані дозволять нам не тільки зробити систему гнучкішою, але і оптимізувати її ще додатково, крім того, що ми вже використовуємо оптимізацію V8 для парсингу JSTP. У більшості форматів серіалізації імена полів теж передаються, в JSON вони займають за грубими оцінками, від 20% до 40% від усього обсягу переданих даних в XML цей відсоток набагато вище половини. Імена полів потрібні тільки для уявної человекочитаемости, хоча як часто люди читають XML або JSON? Для JSTP є два варіанти серіалізації, це повна і скорочена форма, побудована на базі масивів з позиційних зберіганням ключів. Іншими словами, ми один раз передаємо схему, імена полів, їх типи, інші допоміжні метадані з яких на клієнті будуємо прототип. Потім ми отримуємо безліч екземплярів об'єктів, серіалізовать в масиви, тобто імена полів не передаються, а структура масиву позиційно відповідає структурі прототипу, у якого визначені геттери і сетери. Ми просто присвоюємо масиву прототип, він залишається масивом, але ми можемо працювати з цим екземпляром, через імена полів.
Скаффолдинг і інтроспекція застосовується при побудові прозорого з'єднання між клієнтом і сервером (і взагалі між будь-якими процесами, двома серверами або двома клієнтами). При підключенні ми забираємо метадані, що описують расшаренные інтерфейси з методами та їх параметрами і будуємо на протилежній стороні проксі, структурно повторюють віддалене API. Такий проксі можна використовувати локально, працюючи насправді з віддаленим інтерфейсом. Для роботи з предметною областю застосовується метапрограмування і динамічна інтерпретація метамоделей, про що я вже робив багато статей і доповідей (ще за 2014 рік і навіть за 2012 рік), але обов'язково підготую матеріали про метапрограммировании в новому технологічному стеку.
Тепер стають зрозумілими основні ідеї технологічного стека Metarhia і JSTP, як його базової складової:
  • Фокус на структурах даних, а не на алгоритмах,
  • Мінімізація трансформації даних: один формат для постійного зберігання даних на диску або у базі даних, подання даних в оперативній пам'яті на сервері і клієнті, серіалізації та протоколу для передачі по мережі, для опису схем даних, для опису користувацьких інтерфейсів, для мови запитів до даних, інтеграції та обміну даними між програмами та системами.
Як каже Лінус Торвальдс: "Погані програмісти турбуються про коді. Хороші програмісти турбуються про структури даних". А Ерік Реймонд висловив це ще точніше "Розумні структури даних і тупий код працюють набагато краще, ніж навпаки".
Тепер короткі приклади JSTP:
  • Серіалізація структури даних:
    { name: 'Marcus Aurelius', birth: '1990-02-15' }
  • Повна серіалізація об'єкта:
    { name: 'Marcus Aurelius', birth: '1990-02-15', age: () => {...} }
  • Метадані:
    { name: 'string', birth: '[Date]' }
  • Коротка позиційна серіалізація:
    ['Marcus Aurelius','1990-02-15']
  • Мережевий пакет:
    { call: [17, 'interface'], method: ['Marcus Aurelius', '1990-02-15' ] }
Порівняємо опис одних і тих же даних на XML, CLEAR, JSON і JSTP:
Приклад XML
<oilPump name="PT004" displacement="constant" value="63" control= "automatic" status="working">
<flowMeter substance="fluid" recording="off" role="master" period="00:30" dataOutput="Parent.FT002.Verification"/>
<outlet pressure="180" status=working"/>
<failureSensors>
<row><module>Seatings</module><indication>none</indication>
<status>OK</status></row>
<row><module>Flap01</module><indication>open</indication>
<status>OK</status></row>
<row><module>Flap02</module><indication>closed</indication>
<status>overload</status></row>
<row><module>Joint</module><indication>detach</indication>
<status>OK</status></row>
</failureSensors>
</oilPump>

Приклад CLEAR
1: PT004:OilPump Displacement[constant] Value[63] Control[automatic] Status[working]
2: #FlowMeter Substance[fluid] Recording[off] Role[master] Period[00:30] DataOutput[Parent.FT002.Verification]
2: #Outlet Pressure[180] Status[working]
2: #FailureSensors:Table [Module,Indication,Status]
3: [Seatings,none,OK]
3: [Flap01,open,OK]
3: [Flap02,closed,overload]
3: [Joint,detach,OK]

Приклад JSON
{
"name": "PT004",
"type": "OilPump",
"displacement": "constant",
"value": 63,
"control": "automatic",
"status":"working",
"flowMeter": {
"substance": "fluid",
"recording": "off",
"role": "master",
"period": "00:30",
"dataOutput": "Parent.FT002.Verification"
},
"outlet": {
"pressure": 180,
"status": "working",
"failureSensors": [
["Module", "Indication", "Status"],
["Seatings", "ні", "OK"],
["Flap01", "open", "OK"],
["Flap02", "closed", "overload"],
["Joint", "detach", "OK"]
]
}
}

Приклад JSTP
{
name: "PT004",
type: "OilPump",
displacement: "constant",
value: 63,
control: "automatic",
status:"working",
flowMeter: {
substance: "fluid",
recording: "off",
role: "master",
period: "00:30",
dataOutput: "Parent.FT002.Verification",
},
outlet: {
pressure: 180,
status: "working",
failureSensors: [
["Module", "Indication", "Status"],
["Seatings", "ні", "OK"],
["Flap01", "open", "OK"],
["Flap02", "closed", "overload"],
["Joint", "detach", "OK"]
]
}
}

Приклад JSTP мінімізований з застосуванням схеми даних:
["PT004","OilPump","constant",63,"automatic","working",
["fluid","off","master","00:30","Parent.FT002.Verification"],
[180,"working",[["Module","Indication","Status"],
["Seatings","none","OK"],["Flap01","open","OK"],
["Flap02","closed","overload"], ["Joint","detach","OK"]]]]

А тепер увага, найпростіший парсер JSTP на Node.js виглядає так:
api.jstp.parse = (s) => {
let sandbox = api.vm.createContext({});
let js = api.vm.createScript('(' + s + ')');
return js.runInNewContext(sandbox);
};

лише 5 рядків, а його використання просте і очевидне:
api.fs.readFile('./person.record', e, s) => {
let person = api.jstp.parse(s);
console.dir(person);
});

Тепер подивимося більш складний приклад JSTP, що має функції і вирази:
{
name: ['Marcus', 'Aurelius'].join(' '),
passport: 'AE' + '127095',
birth: {
date: new Date('1990-02-15'),
place: 'Rome'
},
age: () => {
var difference = new Date() - birth.date;
return Math.floor(difference / 31536000000);
},
address: {
country: 'Ukraine',
city: 'Kiev',
zip: '03056',
street: 'Pobedy',
building: '37',
floor: '1',
room: '158'
}
}

Як видно, функції можуть звертатися до полів самого об'єкта, але для цього потрібно трохи модифікувати парсер:
api.jstp.parse = (s) => {
let sandbox = vm.createContext({});
let js = vm.createScript('(' + s + ')');
let exported = js.runInNewContext(sandbox);
for (let key in exported) {
sandbox[key] = exported[key];
}
return exported;
};

Моя команда розробників і незалежні розробники готують зараз JSTP SDK для більш ніж десятка мов, а для деяких є вже кілька альтернативних реалізацій. Тестування функціональності і продуктивності JSTP ми проведемо найближчим часом. На сторінці специфікації внизу є зібрані посилання, але не всі, посилання будуть оновлюватися: https://github.com/metarhia/JSTP
Зараз є такі реалізації:
  • JavaScript для Browserа
  • JavaScript для Node.js і Impress Application Server
  • C and C++ for STL and Qt
  • Swift and Objective-C for iOS
  • Java for Android and JavaEE
  • C# for .NET
  • Python, Haskell, PHP, GoLang
Посилання
Висновок
А наступного разу я розповім про інші компоненти стека технологій. Незважаючи на уявну простоту рішень, зробити ще треба дуже багато. Я обіцяю періодично публікувати результати і проводити тести з навантаженням і надійності, порівняння з аналогами по функціональності та ефективності. Поки я не можу рекомендувати все це до масового впровадження, але взимку 2016-2017 ми випустимо SDK з прикладами. Над цим працює кілька десятків осіб у спеціально створеному R&D центрі в Київському Політехнічному Інституті за підтримки SinceTV. Якщо Ви будете стежити за проектом, то сподіваюся, що він Вам ще знадобиться. Навіть часткове впровадження вже дало свої результати. Спасибі за Вашу увагу.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.