gpt4 book ai didi

clojure - core.async pub/sub 在 Om 中表现得很奇怪(clojurescript)

转载 作者:行者123 更新时间:2023-12-04 16:09:20 25 4
gpt4 key购买 nike

为什么我评论时子组件中的计数器更新正常

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

而不是当我在下面代码的父组件中取消注释时?
单击按钮可更新计数器。

我想要实现的是发布/订阅机制,以便组件可以以解耦方式交换消息。

您可以通过创建一个新项目来复制它:
lein new mies-om om-channel-test

然后用下面的代码替换 core.cljs 并运行
lein cljsbuild auto

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

编码:
(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对于子组件发现子组件已经存在,所以没有创建新组件也没有挂载。
  • 但是,“正在运行”/调用 om/build在第 45 行创建了对 event-pub 的新订阅通过 :subscriber/:create-subscriber{:init-state ...}
  • 不会创建一个新组件来创建一个 go-loop 来从这个新的订阅者 channel 消费(没有调用 om/will-mount 来自第 22 行的新组件)
  • 现在 event-pub有两个订阅者但只有一个 go-loop从 channel 消费。在 :event-ch 上的酒吧将阻止 [1] [2]
  • 页面怪异

  • 似乎您不应该在 {:init-state ...} 中产生副作用传递给 om/build .而是通过 event-pub通过 :init-state 到子组件并与 go-loop 一起创建子 chan从中消费。

    [1] http://clojure.github.io/core.async/#clojure.core.async/pub
    “每个项目都并行同步地分发给所有子节点,
    即每个 sub 必须在分发下一个项目之前接受。用
    缓冲/窗口以防止慢速订阅者阻止酒吧。”

    [2] 在第 57 行的 chan 中使用缓冲来查看此行为在几次点击后的变化

    关于clojure - core.async pub/sub 在 Om 中表现得很奇怪(clojurescript),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25917557/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com