2014-09-18 13 views
6

Warum ist der Zähler in der Kindkomponente Aktualisierung gut, wenn ichcore.async pub/sub verhält sich in Om (clojurescript) ungerade

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

und nicht dazu äußern, wenn ich es in der übergeordneten Komponente im Code Kommentar- unten ? Der Zähler wird aktualisiert, indem Sie auf die Schaltfläche klicken.

Was ich versuche zu erreichen ist ein Pub/Sub-Mechanismus, so dass Komponenten Nachrichten in einer entkoppelten Art und Weise austauschen können.

Sie können es replizieren, indem Sie ein neues Projekt zu machen mit:

lein new mies-om om-channel-test 

Dann core.cljs mit folgenden Code ersetzen und

lein cljsbuild auto 

Besuchen Sie die Seite index.html in einem modernen Browser laufen (zum Beispiel das neueste Chrome).

Der Code:

(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

Diese Frage wurde beantwortet auf der Clojurescript Google Gruppe: https://groups.google.com/forum/#!topic/clojurescript/5rCTnnulNXI –

+1

können Sie sich dann selbst beantworten :) – zarkone

Antwort

0

auf https://groups.google.com/forum/#!topic/clojurescript/5rCTfnulNXI beantwortet.

Mit Linie 41 unkommentiert folgenden zu passieren scheint:

  1. Zustand Geordnete Komponente geändert

  2. om/react „wandert“ der Komponentenbaum im Eltern machen, um zu sehen, was

  3. aktualisieren sollte in Zeile 45 mit om/build für die untergeordnete Komponente findet, dass die untergeordnete Komponente bereits existiert, so dass keine neue Komponente erstellt noch angehängt wird.

  4. jedoch „running“/om/build on line aufrufen 45 erstellt ein neues Abonnement für die event-pub durch :subscriber/:create-subscriber in {:init-state ...}

  5. Es wird keine neue Komponente erstellt werden, eine Go-Schleife erzeugen würde von konsumieren dieser neue Teilnehmerkanal (es gibt keinen Anruf om/will-mount für eine neue Komponente von Zeile 22)

  6. Jetzt event-pub hat zwei Teilnehmer, aber nur ein go-loop, die von einem Kanal verbraucht. Das Pub auf :event-ch blockiert [1] [2]

  7. Weirdness auf der Seite

Scheint sollten Sie keine Nebenwirkungen in den {:init-state ...} bestanden om/build haben. Übergeben Sie stattdessen die event-pub an die untergeordnete Komponente über :init-state und erstellen Sie den Subchan zusammen mit der go-loop, um davon zu konsumieren.

[1] http://clojure.github.io/core.async/#clojure.core.async/pub „Jedes Element ist parallel zu allen subs verteilt und synchron, d.h. jede Unter annehmen das nächste Element verteilt wird.Verwenden Sie Pufferung/Windowing langsam U-Boote, um zu verhindern Halt die Kneipe auf.“

[2] Spielen Sie mit Pufferung im chan auf der Leitung 57 diese Verhaltensänderung für ein paar Klicks, um zu sehen