Clojure Sente:Sente在页面加载后向客户端发送跟进消息并销毁视图

时间:2018-06-12 15:19:19

标签: websocket clojure reagent

我很困惑为什么sente在页面初始加载后大约8秒内自己向客户端发送消息。还有什么是奇怪的,如果我在此之前通过websocket快速向服务器发送消息,一切都会稳定下来,并且视图不会崩溃。

作为参考,前端是带有试剂的clojurescript,它是一个发光项目。为了进一步参考,它几乎就是"使用clojure"进行Web开发的第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自己发送消息时,没有数据来更新消息(或者至少是我最好的猜测),因此原子的字段变为空和试剂(反应) .js)试图从vdom中进行差异和补丁。

如果有人知道sente正在做什么,那将非常感激。当您使用Immutant的异步套接字支持时,这个完全相同的设置工作正常,并且自己做很多工作(序列化/反序列化,处理连接等)。

;;;;;;;;

作为后续行动,我通过过滤非零消息解决了这个问题:

(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会在页面加载后向我发送消息。

1 个答案:

答案 0 :(得分:1)

您可以通过查看开发人员工具中的网络标签来检查发生的情况; websocket框架应该有一个子标签。

Sente自己发送一些事件,如果我没记错的话,事件名称(一个关键字是事件向量的第一个元素)在chsk命名空间中。我相信你应该对事件名称使用某种调度,而不是假设只有一种事件会到达。

在重新构建帧的上下文中,我一直在过滤不需要的事件,并将其余事件分派给重新构建的事件循环。我想你可以在luminus做类似的事情。在服务器端,我一直在类似的设置中使用多方法。