ClojureScript,Om和Core.async:如何正确处理事件

时间:2014-05-28 06:45:23

标签: clojurescript core.async om

我已经看过使用Om进行富客户端网站设计。这也是我第一次使用core.async。阅读教程https://github.com/swannodette/om/wiki/Basic-Tutorial我已经看到使用core.async通道来处理删除操作(而不是在处理程序中完成所有工作)。我的印象是使用该通道进行删除只是因为删除回调是在一个范围内声明的,你在该范围内有一个光标在你想要操纵包含该项目的列表的项目级别。

为了获得更多关于频道的见解,我看过Rich Hickey的演讲http://www.infoq.com/presentations/clojure-core-async,他解释了使用频道从事件回调中获取应用逻辑的好主意。这让我想知道教程中删除通道的实际目的是否显示构建应用程序的方式。如果是的话,

  • 与该模式相关的最佳做法是什么?

  • 是否应该为各种活动创建单独的频道?即如果我添加一个控制器来创建一个新事件,我还会为对象创建创建一个新的通道,然后用它来将对象添加到应用程序中另一个地方的全局状态吗?

  • 让我说我有一个项目列表,一个项目有一个详细/简明的状态标志。如果detailed?true,则会显示更多信息,如果detailed?false,则会显示更少的信息。我关联了一个在游标上使用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}
         "..." ])) 

我意识到这可能是一个非常简洁的片段,其中使用通道作为将回调事件与实际逻辑变化分离的手段的总体好处起初看起来不值得付出努力但是更复杂的示例的总体好处超过这个。但另一方面,为这种细节引入额外的通道 - 不详细的切换似乎也为源代码增加了相当大的负载。

如果您能就整个设计问题提供一些提示/提示或其他想法并将其置于透视中,那就太棒了。我觉得有点失落。

1 个答案:

答案 0 :(得分:16)

我使用通道在无法通过游标进行通信的组件之间进行通信。

例如,我在以下时间使用频道:

  • 通信组件不共享应用程序状态(例如,它们的游标指向分层数据结构的不同分支)
  • 在app状态之外实时传递的更改(例如,组件A想要更改组件B的本地状态和组件B不是A的子节点(否则这可以通过传递{{1}来完成} :state
  • 我想与Om组件树之外的东西进行通信

请注意,我希望保持"域状态"在app状态atom和组件本地状态的GUI状态。也就是说, app状态是正在呈现的内容,而本地状态是。 (其中"如何"也指哪个部分)例如,如果您正在编写文本编辑器,则应用程序状态是正在编辑的文档,本地状态是正在编辑的页面,是否选择了粗体等等。

一般情况下,我使用单个通信通道将om/build对放在其上。然后,我使用pubsub来路由邮件。例如,[topic value]使用该主题分发事件,(def p (async/pub ch first))接收主题为(om/sub p my-ch :foo):foo的邮件。我通常将这个单一的通信信道存储在Om的共享状态中。

有时我会使用多个渠道,但我会这样做来设置特定的管道或工作流程,而不是用于通用消息传递。例如,如果我有一个处理组件的管道来处理数据流,那么我可能将其设置为一个通道链,其端点连接到我的Om应用程序。对于一般的UI开发,这种情况很少见。 我还在为我的Om组件使用Qt-esque信号/插槽系统,我还在尝试使用共享信号通道,而每个信号都是自己的通道。我尚未确定哪种方法更好。