[英]core.async pub/sub behaves odd in Om (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}})
在https://groups.google.com/forum/#!topic/clojurescript/5rCTfnulNXI上回答。
在第41行未注釋的情況下,似乎發生了以下情況:
父組件的狀態已更改
om/react
“遍歷”父級渲染中的組件樹以查看應更新的內容
在第45行,子組件的om/build
發現子組件已經存在,因此沒有創建或安裝新組件。
但是,第45行的“運行”/調用om/build
通過以下方式創建了對event-pub
的新訂閱:subscriber/:create-subscriber
in {:init-state ...}
將不會創建一個新組件來創建一個從這個新訂閱者通道使用的循環(對於來自第22行的新組件沒有調用om/will-mount
)
現在event-pub
有兩個訂閱者,但只有一個來自頻道的go-loop
。 酒吧on :event-ch
將阻止[1] [2]
頁面上的怪異
似乎你不應該在傳遞給om/build
的{:init-state ...}
產生副作用。 而是通過:init-state
將event-pub
傳遞給子組件,並與go-loop
一起創建sub chan以從中使用。
[1] http://clojure.github.io/core.async/#clojure.core.async/pub “每個項目並行和同步地分發到所有子項,即每個子項必須在下一個項目分發之前接受。使用緩沖/開窗來防止緩慢的潛水員阻止酒吧。“
[2]在第57行的chan中進行緩沖,以便在幾次點擊時看到此行為更改
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.