Подтвердить что ты не робот

ClojureScript, Om и Core.async: как правильно обрабатывать события

Я посмотрел, как использовать Om для богатого дизайна веб-сайта клиента. Это также мой первый раз, используя core.async. Чтение учебника https://github.com/swannodette/om/wiki/Basic-Tutorial Я видел использование канала core.async для обработки операции удаления (в отличие от выполнения всей работы в обработчике). У меня создалось впечатление, что использование этого канала для удаления было просто сделано, потому что обратный вызов delete был объявлен в области, где у вас есть указатель на уровне элемента, где вы действительно хотите манипулировать списком, содержащим этот элемент.

Чтобы получить больше информации о каналах, я видел, как Rich Hickey говорил http://www.infoq.com/presentations/clojure-core-async, где он объясняет, как неплохо использовать каналы для получения логики приложения вне события -callbacks. Это заставило меня задуматься, действительно ли цель канала удаления в учебнике заключалась в том, чтобы показать этот способ структурирования приложения. Если да,

  • Каковы наилучшие методы, связанные с этим шаблоном?

  • Следует ли создавать отдельные каналы для всех видов событий? То есть Если я добавлю контроллер для создания нового события, могу ли я создать новый канал для создания объектов, который затем используется для того, чтобы объекты добавлялись в глобальное состояние в другом месте приложения?

  • Допустим, у меня есть список элементов, и у одного элемента есть подробный/сжатый флаг состояния. Если detailed? - true, он отобразит больше информации, если detailed? - false, будет отображаться меньше информации. Я связал событие on-click, которое использует om/transact! в курсоре (являющийся представлением элемента списка в глобальном объекте состояния).

(let [toggle-detail-handler 
      (fn [e]
        (om/transact! (get-in myitem [:state])
                      #(conj % {:detailed? (not (:detailed? %))})))]
  (html [:li {:on-click toggle-detail-handler}
         "..." ])) 

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

Было бы здорово, если бы вы могли дать некоторые подсказки/советы или другие мысли по всей проблеме дизайна и поместить их в перспективу. Я чувствую себя немного потерянным там.

4b9b3361

Ответ 1

Я использую каналы для связи между компонентами, которые не могут общаться через курсоры.

Например, я использую каналы, когда:

  • Коммуникационные компоненты не разделяют состояние приложения (например, их курсоры указывают на разные ветки иерархической структуры данных).
  • изменения, передаваемые в реальном времени вне состояния приложения (например, компонент A хочет изменить локальное состояние компонента B, а компонент B не является дочерним элементом A (иначе это можно сделать, передав :state в om/build)
  • Я хочу общаться с чем-то вне дерева компонентов Om

Обратите внимание, что мне нравится сохранять "состояние домена" в атоме состояния приложения и состоянии GUI в локальном состоянии компонента. То есть состояние приложения - это то, что отображается, а - это состояние. (где "как" также относится к какой части) Например, если вы пишете текстовый редактор, состояние приложения - это редактируемый документ, а локальное состояние - это какая страница редактируется, независимо от того, выбран ли полужирный шрифт.

В общем, я использую один канал связи, на который я помещаю пары [topic value]. Затем я использую pub и sub для маршрутизации сообщений. Например, (def p (async/pub ch first)) использовать тему для отправки событий и (om/sub p my-ch :foo) для получения сообщений с темой :foo до my-ch. Обычно я сохраняю этот единственный канал связи в общем состоянии Om.

Иногда я буду использовать несколько каналов, но я бы сделал это, чтобы настроить конкретные конвейеры или рабочие процессы, а не для обмена сообщениями общего назначения. Например, если у меня есть конвейер обработки компонентов, делающих материал для потока данных, тогда я мог бы установить это как цепочку каналов с конечными точками, подключенными к моему приложению Om. Для общего развития пользовательского интерфейса это редко. Я также играю с системой сигналов/слотов Qt-esque для своих компонентов Om, и я все еще экспериментирую с использованием общих каналов сигналов против того, чтобы каждый сигнал был его собственным каналом. Я еще не определился, какой подход лучше.