Эта история также была опубликована в моем личном блоге.

Программирование с помощью 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.

Что вы думаете об этом подходе? Вы бы поступили иначе? Я хотел бы обсудить это!