Clojure Sente:Sente 在页面加载后向客户端发送后续消息并销毁视图
Clojure Sente: Sente sends a follow up message to the client after page load and destroys the view
我很困惑为什么 sente 在页面最初加载后大约 8 秒后自行向客户端发送一条消息。还有什么奇怪的是,如果我在发生这种情况之前通过 websocket 快速向服务器发送消息,一切都会稳定下来并且视图不会崩溃。
作为参考,前端是带有试剂的 clojurescript,它是一个 luminus 项目。为了进一步参考,它几乎完全是 "web development with clojure" 第 5 章中的示例应用程序。
我知道是服务器向客户端推送消息导致了问题,我只是对 Sente 了解不够,无法理解为什么它会这样做。
这是我认为相关的代码:
服务器端:
(defn save-message! [message]
(if-let [errors (validate-message message)]
{:errors errors}
(do
(db/save-message! message)
message)))
(defn handle-message! [{:keys [id client-id ?data]}]
(when (= id :guestbook/add-message)
(let [response (-> ?data
(assoc :timestamp (java.util.Date.))
save-message!)]
(if (:errors response)
(chsk-send! client-id [:guestbook/error response])
(doseq [uid (:any @connected-uids)]
(chsk-send! uid [:guestbook/add-message response]))))))
客户端(带试剂):
(defn response-handler [messages fields errors]
(fn [{[_ message] :?data}]
(if-let [response-errors (:errors message)]
(reset! errors response-errors)
(do
;; Fires right before the view crashes!
(.log js/console "response-handled")
(reset! errors nil)
(reset! fields nil)
(swap! messages conj message)))))
(defn home []
(let [messages (atom nil)
fields (atom nil)
errors (atom nil)]
(ws/start-router! (response-handler messages fields errors))
(get-messages messages)
(fn []
[:div
[:div.row
[:div.span12
[message-list messages]]]
[:div.row
[:div.span12
[message-form fields errors]]]])))
问题是,当 sente 自己发送消息时,没有数据来更新消息(或者至少这是我最好的猜测),因此原子的字段变为空并且 reagent (react.js) 抛出尝试从 vdom 中区分和修补。
如果有人知道 sente 在做什么,将不胜感激。当您使用 Immutant 的异步套接字支持并自己完成大量工作(serialize/deserialize、处理连接等)时,这种完全相同的设置工作正常。
;;;;;;;
作为跟进,我通过过滤非零消息解决了这个问题:
(defn response-handler [messages fields errors]
(fn [{[_ message] :?data}]
(if-let [response-errors (:errors message)]
(reset! errors response-errors)
(when (not= message nil)
(reset! errors nil)
(reset! fields nil)
(swap! messages conj message)))))
不过,这是一种绷带解决方案,如果不立即使用套接字,我很想知道为什么 Sente 在页面加载后向我抛出消息。
您可以通过查看开发人员工具中的网络选项卡来检查发生了什么; websocket 框架应该有一个子选项卡。
Sente 自己发送一些事件,如果我没记错的话,事件名称(一个关键字,它是事件向量的第一个元素)在 chsk
命名空间中。我相信您无论如何都应该对事件名称使用某种调度,而不是假设只有一种事件会到达。
在 re-frame 的上下文中,我一直在过滤不需要的事件并将其余事件分派到 re-frame 事件循环。我想你可以在 luminus 中做类似的事情。在服务器端,我一直在类似的设置中使用 multimethods。
我很困惑为什么 sente 在页面最初加载后大约 8 秒后自行向客户端发送一条消息。还有什么奇怪的是,如果我在发生这种情况之前通过 websocket 快速向服务器发送消息,一切都会稳定下来并且视图不会崩溃。
作为参考,前端是带有试剂的 clojurescript,它是一个 luminus 项目。为了进一步参考,它几乎完全是 "web development with clojure" 第 5 章中的示例应用程序。
我知道是服务器向客户端推送消息导致了问题,我只是对 Sente 了解不够,无法理解为什么它会这样做。
这是我认为相关的代码:
服务器端:
(defn save-message! [message]
(if-let [errors (validate-message message)]
{:errors errors}
(do
(db/save-message! message)
message)))
(defn handle-message! [{:keys [id client-id ?data]}]
(when (= id :guestbook/add-message)
(let [response (-> ?data
(assoc :timestamp (java.util.Date.))
save-message!)]
(if (:errors response)
(chsk-send! client-id [:guestbook/error response])
(doseq [uid (:any @connected-uids)]
(chsk-send! uid [:guestbook/add-message response]))))))
客户端(带试剂):
(defn response-handler [messages fields errors]
(fn [{[_ message] :?data}]
(if-let [response-errors (:errors message)]
(reset! errors response-errors)
(do
;; Fires right before the view crashes!
(.log js/console "response-handled")
(reset! errors nil)
(reset! fields nil)
(swap! messages conj message)))))
(defn home []
(let [messages (atom nil)
fields (atom nil)
errors (atom nil)]
(ws/start-router! (response-handler messages fields errors))
(get-messages messages)
(fn []
[:div
[:div.row
[:div.span12
[message-list messages]]]
[:div.row
[:div.span12
[message-form fields errors]]]])))
问题是,当 sente 自己发送消息时,没有数据来更新消息(或者至少这是我最好的猜测),因此原子的字段变为空并且 reagent (react.js) 抛出尝试从 vdom 中区分和修补。
如果有人知道 sente 在做什么,将不胜感激。当您使用 Immutant 的异步套接字支持并自己完成大量工作(serialize/deserialize、处理连接等)时,这种完全相同的设置工作正常。
;;;;;;;
作为跟进,我通过过滤非零消息解决了这个问题:
(defn response-handler [messages fields errors]
(fn [{[_ message] :?data}]
(if-let [response-errors (:errors message)]
(reset! errors response-errors)
(when (not= message nil)
(reset! errors nil)
(reset! fields nil)
(swap! messages conj message)))))
不过,这是一种绷带解决方案,如果不立即使用套接字,我很想知道为什么 Sente 在页面加载后向我抛出消息。
您可以通过查看开发人员工具中的网络选项卡来检查发生了什么; websocket 框架应该有一个子选项卡。
Sente 自己发送一些事件,如果我没记错的话,事件名称(一个关键字,它是事件向量的第一个元素)在 chsk
命名空间中。我相信您无论如何都应该对事件名称使用某种调度,而不是假设只有一种事件会到达。
在 re-frame 的上下文中,我一直在过滤不需要的事件并将其余事件分派到 re-frame 事件循环。我想你可以在 luminus 中做类似的事情。在服务器端,我一直在类似的设置中使用 multimethods。