core.async的pub/sub表现在庵(clojurescript)奇

问题描述:

为什么在子组件计数器更新很好,当我评论core.async的pub/sub表现在庵(clojurescript)奇

(om/update-state! owner :clicked not) 

而不是当我在代码中取消注释就出现在父组件的下方? 通过单击按钮更新计数器。

我想要完成的是一个pub/sub机制,所以组件可以以分离的方式交换消息。

您可以通过一个新的项目,将它复制:

lein new mies-om om-channel-test 

然后替换下面的代码core.cljs和运行

lein cljsbuild auto 

访问index.html页面在一个现代浏览器(例如最新的Chrome)。

的代码:

(ns om-channel-test.core 
    (:require-macros [cljs.core.async.macros :refer (go)]) 
    (:require [om.core :as om :include-macros true] 
      [om.dom :as dom :include-macros true] 
      [cljs.core.async :refer [chan pub <! sub >! timeout put!]])) 

(enable-console-print!) 

(def app-state (atom {:text "Hello world!"})) 

(def event-ch (chan)) 

(def event-pub 
    (pub event-ch #(:topic %))) 

(defn child [cursor owner] 
    (reify 
    om/IInitState 
    (init-state [_] 
     {:counter 0}) 
    om/IWillMount 
    (will-mount [_] 
     (go (loop [] (<! (om/get-state owner :subscriber)) 
       (println "message received") 
       (om/update-state! owner :counter inc) 
       (recur)))) 
    om/IRender 
    (render [_] 
     (println "rendering child") 
     (dom/p nil (om/get-state owner :counter))) 
    om/IWillUnmount 
    (will-unmount [_] 
     (println "unmount")))) 

(defn parent [cursor owner] 
    (om/component 
    (println "rendering parent") 
    (dom/div nil 
      (dom/button #js {:onClick 
          #(do 
           #_(om/update-state! owner :clicked not) 
           (go (>! event-ch {:topic :wizard 
                :message "hello"})))} 
         "Click") 
      (om/build child 
         cursor 
         {:init-state 
         {:subscriber 
         ((om/get-shared owner :create-subscriber) :wizard)}})))) 

(om/root 
parent 
app-state 
{:target (. js/document (getElementById "app")) 
    :shared {:create-subscriber (fn [topic] 
           (sub event-pub 
            topic (chan))) 
      :event-ch event-ch}}) 
+1

这个问题已经被在clojurescript谷歌组上回答:https://groups.google.com/forum/#!topic/clojurescript/5rCTfnulNXI – 2014-09-19 07:54:05

+1

你可以自我回答:) – zarkone 2015-07-29 06:06:49

回答上https://groups.google.com/forum/#!topic/clojurescript/5rCTfnulNXI

随着行41注释掉以下似乎发生:

  1. 父组件的状态改变

  2. om/react“走出去”,在父母的组件树呈现,看看有什么需要更新

  3. 对于子组件,在第45行用om/build查找子组件已经存在,所以没有创建新组件或未安装新组件。

  4. 然而,“运行” /电话线45 om/build{:init-state ...}

  5. 创建一个新的订阅到event-pub通过:subscriber/:create-subscriber不会有创建一个新的组件,这将产生一个去环,从消费这个新的用户渠道(从有22行对om/will-mount没有呼吁一个新的组件)

  6. 现在event-pub有两个用户,但只有一个go-loop从一个通道消耗。在:event-ch这家酒吧将阻止页面

好像你不应该有在{:init-state ...}传递给om/build副作用的[1] [2]

  • 怪诞。而是通过:init-stateevent-pub传递给子组件,并创建子陈以及go-loop以从中消耗。

    [1] http://clojure.github.io/core.async/#clojure.core.async/pub “每个项目并行且同步地分配给所有子项目,即每个子项目必须在分配下一个项目之前接受。使用 缓冲/窗口,以防止慢潜艇持有了酒吧。”

    [2]玩弄缓冲浐在线57看到这种行为改变的一对夫妇的点击