Поскольку люди часто интересуются версией моего приложения Elm на Typescript и RxJs (весь код из моего выступления на Haskell/Elm FullStack 2016, см. этот пост для получения ресурсов), кажется полезным написать что-нибудь о том, где найти этот код и добавить немного комментирует его цель в разговоре. Обратите внимание, что это краткое руководство по некоторым ключевым моментам кода, а не полное объяснение.

Просмотрите код
Самый быстрый способ просмотреть код Typescript и RxJs — это просмотреть исходный код в онлайн-приложении с помощью Chrome devTools (или вашего предпочтительного браузер). Хотя Typescript работает как транспилированный код, магия исходных карт означает, что браузер с радостью отображает файлы .ts и поддерживает точки останова и отладку с ними.

Клонировать код
Репозиторий кода находится здесь: https://github.com/jkbits1/HaskellElmTalk/tree/master/rxjs/src

Соответствующие файлы и комментарии — машинописный текст
Из трех файлов .ts только два имеют непосредственное отношение к данному вопросу. В основной части приложения (app.ts) используется модуль, определенный в wheelCalcs.ts. Этот модуль содержит типы плюс связанные функции алгоритма. Функции определяются и экспортируются в классе Calcs1. Эквиваленты типов Elm определяются непосредственно над этим классом.

Соответствующие файлы и комментарии — RxJs
Код Rx находится в app.ts. Angular2 находился в постоянном движении до выпуска, и предыдущее использование EventEmitter в этом приложении для реагирования на изменения ввода теперь устарело. Здесь он заменен на RxSubject, который работает как прямая замена. Полезно, что RxSubject имеет метод asObservable(), поэтому подписчики видят только наблюдаемый объект, а не сам субъект.

RxSubject полезен, когда нам нужен объект, который, как форма прокси, может как наблюдать за данными, так и быть подписанным одним или несколькими наблюдателями. Одной из тем здесь является BehaviorSubject, которая предоставляет начальное значение подписчикам. В терминах Rx это делает BehaviorSubject «горячим» наблюдаемым, а остальные «холодными». Начальное значение инициирует первое использование алгоритма и, таким образом, отображает первоначальные результаты.

Альтернативным подходом к использованию RxSubject является импорт ReactiveFormsModule из Angular2 и применение директивы formControl к определенным полям. Затем эти поля становятся наблюдаемыми напрямую. Код подписки одинаков для обоих подходов.

Наш код подписки довольно прост. Мы выполняем стандартный debounce и реагируем только на фактические изменения на входе. Однако теперь, когда у нас есть данные в виде потоков Rx, было бы очень просто объединять и фильтровать данные из полей или вносить изменения в соответствии со значениями нескольких полей и т. д. Код оставался бы столь же декларативным.

input
.debounceTime(50)
.distinctUntilChanged()
.subscribe(
   this.updateModel(this, results, wheelPos),
…
);

updateModel() является эквивалентом этой функции в приложении Elm. Он получает измененный ввод и пересчитывает алгоритм, что приводит к обновлению представления/интерфейса. Таким образом, приложение следует однонаправленному шаблону приложения Elm, и в целом его поведение определяется в декларативном стиле.

Эквивалентный код приложения Elm
Чтобы сравнить приложение TS/Rx с приложением Elm (также созданным как модуль и основное приложение), вот ссылки на репозитории: puzzle2-ui .elm, PuzzleModule.elm

Приведенный выше код wheelCalcs.ts является преобразованием Elm PuzzleModule. Вы можете просмотреть онлайн-приложение Elm (однако для Elm нет сопоставления источников). Нажмите кнопку Повернуть, чтобы поэкспериментировать с колесом головоломки D3, и обратите внимание, как поля ввода настраиваются автоматически. Присущий Elm однонаправленный стиль позволяет легко иметь поля ввода, информационные элементы и т. д., работающие в гармонии.

Мысли о Rx по сравнению с Elm
Мне очень нравится мощность и выразительность Rx. Он обеспечивает декларативное программирование для широкого круга языков и сред, из которых в этом примере мы видим лишь малую часть. Elm определенно показал, что он создает отказоустойчивые браузерные приложения, которые работают, как и планировалось, и это немалый подвиг! Однако, хотя Elm 0.17 сделал язык более доступным, он отошел от своих истоков FRP. Это заставило меня задаться вопросом, насколько легко по-прежнему создавать различные формы функциональности в стиле Rx в Elm. В будущем, возможно, мне нужно будет принять решение о том, подходят ли проекты для одной или другой технологии, а не для обеих. Я планирую провести некоторые тесты и, возможно, когда-нибудь напишу об этом пост.

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