阻塞直到 DOM 事件发生 core.async
Block until a DOM event occurs with core.async
我有一个 Clojurescript 项目,我需要阻止整个线程执行,直到发生 DOM 事件。
在这种情况下,事件是 DOMContentLoaded,当初始 HTML 文档已完全加载和解析时触发。但它可以扩展到任何 DOM(或非 DOM)事件。
由于我是 Clojurescript 和异步的新手,所以我不确定如何解决这个问题。我的第一个猜测是使用 core.async 库。经过一些文档抓取后,我有了这个功能:
(defn wait-dom-loading
[]
(let [c (async/chan)]
{1} (.addEventListener js/document "DOMContentLoaded" (fn [] (async/go (async/>! c true))))
{2} (async/go (async/<! c))))
我的理解是 {2} 从 chan c 获取 并停放直到 {1} 中的听众评估函数和 puts chan c.
中的一个值
因为我几乎不了解如何对异步代码进行单元测试(除了将其放入(异步完成)表达式并在完成时调用 done)我无法验证我所做的是否正确。我试过这个片段:
(do
(wait-dom-loading)
(-> (dommy/sel1 :p)
(dommy/set-text! "Loaded !")))
在 html 页面内有一个 p 块,并注意到控制台抱怨 js 代码试图操纵一个 DOM 对象'还存在。这证实了我所做的并没有按计划工作。
- 这个例子中似乎有什么问题?
- 这是矫枉过正吗?我可以用更小的解决方案甚至 gasp 内置函数来解决这个问题吗?
- 将我的脚本放在我的 html 页面底部是不是很糟糕的做法?
因为这是我关于堆栈溢出的第一个问题,我希望它写得足够好。
我会这样做:
(ns domevent.core
(:require [cljs.core.async :as async :refer [chan]])
(:require-macros [cljs.core.async.macros :refer [go]]))
(enable-console-print!)
(def ch (chan))
(go
(pr "i am waiting")
(pr (<! ch))
(dommy/set-text! (dommy/sel1 :p) "Loaded !"))
(.addEventListener js/document "DOMContentLoaded" (fn [] (go (>! ch "hello"))))
或者更简单地说:
(let [ch (chan)]
(go
(pr "i am waiting")
(<! ch)
(dommy/set-text! (dommy/sel1 :p) "Loaded !"))
(.addEventListener js/document "DOMContentLoaded" #(close! ch)))
)
这里的重点是reader和writer共享的ch。当 (<! ch)
发生时,ch 中还没有任何内容,因此该线程被停放(即停止并等待任何内容出现在 ch 中)。同时,DOMContentLoaded 发生,处理程序写入通道。那么之前的话题继续。
我有一个 Clojurescript 项目,我需要阻止整个线程执行,直到发生 DOM 事件。
在这种情况下,事件是 DOMContentLoaded,当初始 HTML 文档已完全加载和解析时触发。但它可以扩展到任何 DOM(或非 DOM)事件。
由于我是 Clojurescript 和异步的新手,所以我不确定如何解决这个问题。我的第一个猜测是使用 core.async 库。经过一些文档抓取后,我有了这个功能:
(defn wait-dom-loading
[]
(let [c (async/chan)]
{1} (.addEventListener js/document "DOMContentLoaded" (fn [] (async/go (async/>! c true))))
{2} (async/go (async/<! c))))
我的理解是 {2} 从 chan c 获取 并停放直到 {1} 中的听众评估函数和 puts chan c.
中的一个值因为我几乎不了解如何对异步代码进行单元测试(除了将其放入(异步完成)表达式并在完成时调用 done)我无法验证我所做的是否正确。我试过这个片段:
(do
(wait-dom-loading)
(-> (dommy/sel1 :p)
(dommy/set-text! "Loaded !")))
在 html 页面内有一个 p 块,并注意到控制台抱怨 js 代码试图操纵一个 DOM 对象'还存在。这证实了我所做的并没有按计划工作。
- 这个例子中似乎有什么问题?
- 这是矫枉过正吗?我可以用更小的解决方案甚至 gasp 内置函数来解决这个问题吗?
- 将我的脚本放在我的 html 页面底部是不是很糟糕的做法?
因为这是我关于堆栈溢出的第一个问题,我希望它写得足够好。
我会这样做:
(ns domevent.core
(:require [cljs.core.async :as async :refer [chan]])
(:require-macros [cljs.core.async.macros :refer [go]]))
(enable-console-print!)
(def ch (chan))
(go
(pr "i am waiting")
(pr (<! ch))
(dommy/set-text! (dommy/sel1 :p) "Loaded !"))
(.addEventListener js/document "DOMContentLoaded" (fn [] (go (>! ch "hello"))))
或者更简单地说:
(let [ch (chan)]
(go
(pr "i am waiting")
(<! ch)
(dommy/set-text! (dommy/sel1 :p) "Loaded !"))
(.addEventListener js/document "DOMContentLoaded" #(close! ch)))
)
这里的重点是reader和writer共享的ch。当 (<! ch)
发生时,ch 中还没有任何内容,因此该线程被停放(即停止并等待任何内容出现在 ch 中)。同时,DOMContentLoaded 发生,处理程序写入通道。那么之前的话题继续。