Я совершенно не понимаю, почему sente отправляет клиенту сообщение само по себе примерно через 8 секунд после начальной загрузки страницы.Что еще странно, так это то, что если я быстро отправлю сообщение на сервер через веб-сокет до того, как это произойдет, все стабилизируется, и представление не будет аварийно завершено.
Для справки: передний конец - это clojurescript с реагентоми его проект Luminus.Для дальнейшего ознакомления, это почти точно пример приложения из главы 5 «Веб-разработка с clojure».
Я могу сказать, что если сервер отправляет сообщение клиенту, вызывающему проблему, я просто недостаточно знаю о 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 отправляет сообщение самостоятельно, нет данных для обновления сообщений (или, по крайней мере, это моя лучшая догадка), поэтому поля атома становятся нулевыми, а броски реактивов (реагировать на ошибки), пытаясь найти и исправить из vdom,
Если кто-нибудь знает, что делает сенте, он будет очень признателен.Точно такая же настройка отлично работает, когда вы используете поддержку асинхронных сокетов Immutant и выполняете большую часть работы самостоятельно (сериализация / десериализация, обработка соединений и т. Д.).
;;;;;;;;
В качестве продолжения я решил проблему, отфильтровав сообщения, отличные от nil:
(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 отправляет сообщение вme после загрузки страницы, если сокет не используется сразу.