Эта история также была опубликована в моем личном блоге.
Программирование с помощью Cycle.js/Rx.js требует от вас другого подхода к коду. Мы должны переключить ваш мозг, чтобы он думал с другой парадигмой — функциональной и реактивной, а не императивной и пассивной.
К сожалению, не хватает конкретного примера, из конкретных фич, из реального применения.
Поскольку я создаю инструмент для анализа метрик Канбан с доски Trello с помощью Cycle.js, у меня есть конкретные примеры.
Вот один пример использования, которым я хочу поделиться с вами, чтобы проиллюстрировать, как вы справляетесь с пользователем, нажимающим кнопку для выполнения действия, когда все является потоком.
Особенность
Cumulative Flow Diagram (CFD) — классная метрика, которая поможет вам понять, что происходит с нашим Канбан-потоком. В TKAT данные берутся из API Trello, консолидируются, а затем анализируются для их создания.
Однако эта метрика содержится во внутренностях веб-приложения. Это неудобно, если мы хотим повторно использовать или делиться этой информацией каким-либо образом (например, для создания глобального отчета для внешних заинтересованных сторон).
Что, если данные были проанализированы, и мы можем скачать .csv? Это было бы круто.
Создание потрясающего, по одному потоку за раз
С точки зрения пользователя, нам бы хотелось, чтобы кнопка «Загрузить» находилась где-то рядом с графиком — возможно, чуть ниже. При нажатии на эту кнопку будет загружен .csv текущего графика.
Если мы изменим период/диапазон выбранных списков, а затем нажмем кнопку загрузки, он должен продолжать соответствовать отображаемому графику. Мы сможем снова нарисовать этот график после того, как импортируем наши данные в Excel/GSheet.
Другими словами: каждый раз, когда происходит нажатие на кнопку, загружайте в формате CSV последние данные.
Давайте интерпретируем это в терминах Cycle.js:
- "каждый раз...": подписаться на следующий поток
- «… происходит щелчок по кнопке, …»: downloadClicks$, поток, представляющий нажатия кнопки
- «…загрузить в формате CSV…»: побочный эффект, выполняемый специальным драйвером ExportToCSV.
- «… последние данные».: csvData$, поток, представляющий данные
Уже есть поток, содержащий данные CFD, так как мы их уже отображаем. Нам просто нужно сопоставить их, чтобы создать csvData$, соответствующий входному формату драйвера ExportToCSV.
Затем нам нужно объединить наши потоки, чтобы получить последнее значение из csvData$ всякий раз — и только тогда — когда элемент создается в downloadClicks$.
Готовьтесь, для этого есть оператор Rx.js: withLatestFrom().
Вот чего мы хотим добиться:
Объединение наших потоков создаст еще один (downloadData$), который будет выдавать элемент, содержащий данные в формате CSV, всякий раз, когда происходит щелчок по кнопке.
Что с загрузкой?
Загрузка CSV-файла из отформатированных данных выглядит как работа для водителя!
Действительно, такого рода операции влекут за собой побочные эффекты, поскольку программе необходимо вывести что-то, что будет видно пользователю. Это та часть, где наше приложение раскрывает свою ценность. Это также та часть, где могут лежать неприятные ошибки, касающиеся среды, глобального состояния машины и т. д.
Вот почему мы предпочитаем переместить эту часть в специальный драйвер, подальше от логики нашего приложения.
Примечание. Я не нашел драйвера «downloadToCsv» с открытым исходным кодом во время реализации этой функции, поэтому я создал свой собственный для этого проекта. Однако с очень небольшим рефакторингом его можно легко сделать открытым исходным кодом.
Драйвер подписывается на наблюдаемый (= поток) ввод.
Каждый раз, когда он создает событие, содержащее отформатированные данные, он выполняет побочный эффект: загружает CSV-файл из этих данных. Таким образом, мы просто передаем наш поток downloadData$, и все готово!
Вот PR, который реализовал эту функцию, если вы хотите прочитать конкретный diff.
Что вы думаете об этом подходе? Вы бы поступили иначе? Я хотел бы обсудить это!