簡體   English   中英

core.async pub / sub在Om中表現奇數(clojurescript)

[英]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行未注釋的情況下,似乎發生了以下情況:

  1. 父組件的狀態已更改

  2. om/react “遍歷”父級渲染中的組件樹以查看應更新的內容

  3. 在第45行,子組件的om/build發現子組件已經存在,因此沒有創建或安裝新組件。

  4. 但是,第45行的“運行”/調用om/build通過以下方式創建了對event-pub的新訂閱:subscriber/:create-subscriber in {:init-state ...}

  5. 將不會創建一個新組件來創建一個從這個新訂閱者通道使用的循環(對於來自第22行的新組件沒有調用om/will-mount

  6. 現在event-pub有兩個訂閱者,但只有一個來自頻道的go-loop 酒吧on :event-ch將阻止[1] [2]

  7. 頁面上的怪異

似乎你不應該在傳遞給om/build{:init-state ...}產生副作用。 而是通過:init-stateevent-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM