20

我看过使用 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}
         "..." ])) 

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

如果您能就整个设计问题提供一些提示/提示或其他想法并将它们放在透视图中,那就太好了。我在那里感到有些失落。

4

1 回答 1

16

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

例如,我在以下情况下使用渠道:

  • 通信组件不共享应用程序状态(例如,它们的光标指向分层数据结构的不同分支)
  • 在应用程序状态之外实时传达的更改(例如,组件 A 想要更改组件 B 的本地状态并且组件 B 不是 A 的子级(否则可以通过传递:state到来完成om/build
  • 我想与 Om 组件树之外的东西进行通信

请注意,我喜欢将“域状态”保留在应用程序状态原子中,并将 GUI 状态保留在组件本地状态中。也就是说,应用程序状态是正在呈现的内容,本地状态是如何呈现的。(其中“如何”也指哪个部分)例如,如果您正在编写文本编辑器,则应用状态是正在编辑的文档,本地状态是正在编辑的页面,是否选择了粗体等等。

通常,我使用单个通信通道来放置[topic value]对。然后我使用pubsub来路由消息。例如,(def p (async/pub ch first))使用主题来调度事件和(om/sub p my-ch :foo)接收带有主题:foo的消息my-ch。我通常将这个单一的通信通道存储在 Om 的共享状态中。

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

于 2014-06-10T14:23:21.897 回答