我正在尝试在 clojurescript/reagent 中做一些定时动画,并且我正在尝试使用 core.async 来按顺序实现一系列定时步骤。我正在使用第三方 js React 库,因此,要调用它的函数,我使用的是 (fn [] ^js (.function (.something @ref)) 形式。但是,将此匿名函数放入 go 块中,如下所示以下不起作用 -
(go
(js/console.log "going")
(<! (timeout 3000))
(fn [] ^js (.function (.somedata @lib))
(js/console.log "landed")
)
这将返回正确计时的“going”和“landed”,并且在将另一个 console.log 函数放在其位置时起作用。但是,如果您将此 console.log 包装在 Fn 中,它将不再被调用。它在组件的 :on-click 处理程序中被调用。我错过了什么?
那个
^js
没有必要。
当您将某些内容包裹在
(fn [] ...)
中时,除非调用 fn
,否则不会调用该内容。 IE。 ((fn [] ...))
。但是,您最终会创建一个函数并立即调用它,这是完全没有必要的。
所以,假设我理解正确,您可以简单地将
(fn [] ^js ...)
替换为 (-> @lib .somedata .function)
。
顺便说一句,
somedata
听起来像是一个包含一些数据的字段,而不是需要调用的函数。如果是这种情况,请使用 .-somedata
而不是 .somedata
。
正如 Eugene Pakhomov 所提到的,使用
(fn [] ...)
只创建一个函数,而不调用它。因此它基本上只是完全消除而不做任何事情。
你在这里的动机似乎摆脱了推理警告。所以根本的问题是
core.async
在输入提示时相当健忘。如果你问我,你根本不应该在 go
块中进行任何互操作,而应该将其全部移出。通过 defn
或 go
之外的局部函数。
(defn do-something []
(.function (.somedata ^js @lib)))
(go
(js/console.log "going")
(<! (timeout 3000))
(do-something)
(js/console.log "landed"))
(let [do-something (fn [] (.function (.somedata ^js @lib)))]
(go
(js/console.log "going")
(<! (timeout 3000))
(do-something)
(js/console.log "landed")))
另外,请注意一点。为此使用 core.async 将大大增加为
go
块中的代码生成的代码量。如果您确实需要延迟某些事情,请使用(js/setTimeout do-something 3000)
。谨慎使用 go
,它很容易为某些事情生成比通常需要的代码多 10 倍的代码。