首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Om + Figwheel + core.async编写可重载的异步代码?

如何使用Om + Figwheel + core.async编写可重载的异步代码?
EN

Stack Overflow用户
提问于 2015-05-16 06:37:12
回答 2查看 470关注 0票数 4

我想写一些像时钟应用程序的东西。状态基本上是一个重复递增的数字。这里可以看到一种方法。

代码语言:javascript
复制
(ns chest-example.core
  (:require [om.core :as om :include-macros true]
            [om.dom :as dom :include-macros true]
            [cljs.core.async :as async])
  (:require-macros [cljs.core.async.macros :refer [go]]))

(defonce app-state (atom {:time 0}))

(defn clock-view [data owner]
  (reify
    om/IRender
    (render [_]
      (dom/div nil (pr-str data)))))

(go (while true
  (async/<! (async/timeout 1000))
  (om/transact! (om/root-cursor app-state) :time inc)))

(defn main []
  (om/root
    clock-view
    app-state
    { :target (. js/document (getElementById "clock"))}))

我的问题是这不是可重载的代码。一旦我通过无花果轮刷新代码,增量就会变得更快,因为有几件事会更新状态。

我试图尝试各种想法(基本上是让不同的组件拥有go语句代码),但我不能想出一些可以工作的东西。

有没有人有一个很好的解决方案,或者我只需要在开发过程中坚持使用它?

EN

回答 2

Stack Overflow用户

发布于 2015-05-16 18:05:44

您必须告诉goroutine何时停止运行。要做到这一点,最简单的方法是发送close!告诉goroutine:

代码语言:javascript
复制
(ns myproject.core
  ;; imports
  )

(def my-goroutine
  (go-loop []
    (when (async/<! (async/timeout 1000))
      (om/transact! (om/root-cursor app-state) :time inc)
      (recur)))))

;; put in your on-reload function for figwheel
(defn on-reload []
  (async/close! my-goroutine))

任何在循环中运行的goroutine都需要在重新加载时被通知停止(通过figwheel的:on-jsload配置)。

代码语言:javascript
复制
;; project.clj
(defproject ;; ...
  :figwheel {:on-jsload "myproject.core/on-reload"}
)

最好将长时间运行的goroutines视为需要管理的资源。在golang中,将长时间运行的goroutines视为进程/tombstones以确保正确的拆卸是一种常见的模式。同样的情况也应该应用于core.async的goroutines。

票数 2
EN

Stack Overflow用户

发布于 2015-05-21 10:55:14

好的。在读完建议后,我自己尝试实现了一些东西。我不能说这是最好的解决方案,所以反馈是受欢迎的,但它似乎是有效的。基本上它是按照Charles的建议来做的。我把它包装在一个组件中,当组件本身被添加或删除时,该组件有回调。我认为这将很难做到这一点,无论如何,与图轮上的钩子。

高低价!这样我们就可以从两个通道获取输入。当组件从DOM中“移除”时,它会向alts发送:killed信号!这会退出循环。

时钟控制器不渲染任何东西,它基本上只是为了保持时钟滴答作响,并更新应用程序状态,而不是通过光标被任意其他组件使用。

代码语言:javascript
复制
(defn clock-controller [state owner]
  (reify
    om/IInitState
      (init-state [_]
        {:channel (async/chan)})
    om/IWillMount
    (will-mount [_]
      (go (loop []
        (let [c (om/get-state owner :channel)
              [v ch] (async/alts! [(async/timeout 1000) c])]
          (if (= v :killed)
            nil
            (do
              (om/transact! state :time (fn [x] (+ x 1)))
              (recur)))))))
    om/IWillUnmount
    (will-unmount [_]
      (let [c (om/get-state owner :channel)]
        (go
          (async/>! c :killed)
          (async/close! c))))
    om/IRender
    (render [_])))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30269754

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档