2024年Clojure调查中分享您的想法!

欢迎!请参阅关于页面以了解更多关于如何使用本站的信息。

0
core.async

目前,在较新浏览器上(<! (timeout 0))的执行时间大约为4毫秒,因为其结果将是.即使在提供0毫秒的情况下,现代浏览器的setTimeout也不会在4毫秒以下返回。如果只是想让浏览器最小程度地回控时间,4毫秒将过于漫长。

参考
https://github.com/clojure/core.async/blo 本统d073896192fa55fab992eb4c9ea57b86ec5cf076/src/main/clojure/cljs/core/async/impl/timers.cljs#L161-L164

接下来是
https://github.com/clojure/core.async/blob/d073896192fa55fab992eb4c9ea57b86ec5cf076/src/main/clojure/cljs/core/async/impl/dispatch.cljs#L35-L36

我在想象这个小重构

(defn queue-delay (link: f delay)
(if (= 0 delay)

  (goog.async.nextTick f)      ;;  <---- new path for 0
 (js/setTimeout f delay))      ;;  <---- existing path

11 答案

0

评论者:pkobrien

我认为使用goog.Timer.callOnce对于任何时间长度都适用,并仍将解决问题,即js/setTimeout的使用。

0

评论者:mikethompson

从我所能看到的,goog.Timer.callOnce使用setTimeout。但在0毫秒持续时间的情况下,我们正在尝试避免的问题正是这个。所以我看不到callOnce是一个解决方案。

0

评论者:pkobrien

我想你是对的,Mike。尽管谷歌显然知道这个问题,但事实是难以置信的。但现在我在重读goog.Timer代码时,我看不出他们在这里已经修复了它。看起来goog.async.nextTick是唯一解决方案。

0
by

评论者:pkobrien

我只是想提一下,这个问题是关于 core.async 的 ClojureScript 版本的,而且看起来使用 (<! (timeout 0)) 作为将控制权暂时交还给 js 事件处理的方式相当强调。因此,我认为这非常重要,要使其尽可能高效。

0
by

评论者:gshayban

阅读这个“错误”时,似乎实际问题是 CLJS 中的 goblock 分发更加多样化。它可以/应该得到改进,但使 (<! (timeout 0)) -- 没有意义的代码 -- 表现不同并不能以有意义的方式解决问题。

我们应该从根本上消除这种黑客行为的需求,而不是使未定义的行为更加具体。ASYNC-131 和 ASYNC-43 相关,可能是更好的起点。

0
by

评论者:mikethompson

@Ghadi
1.我看不出问题 131 与其紧密相关,可以作为“更好的起点”。它有不同的方向,代表不同的需求,并且可能需要不同的解决方案(如当前的建议所示)。

  1. 从 David Nolen 注明的 Google Closure 分发选项切换来看,几乎看起来像问题 43 可以关闭。顺便说一下,我的建议是确实使用 goog.async.nextTick(因此我遵循 Google Closure 方法)。

此外,我不同意您的说法,认为 (<! (timeout 0)) 是“没有意义的代码”。在单线程环境,如浏览器中,有时需要在 go 循环中明确地将控制权“交回”浏览器(如果该 go 循环暂时占用 CPU)。目前 (<! (timeout 0)) 是我唯一知道这样做的方法。它可以修改为 (<! (yield-cpu)) 以使意图更明确,这可能很棒,但重要的是要有一个放弃的方式,它不必总是花费 4ms。我相信这个需求是真实的,非常有意义 :-)

0
by

评论者:mikethompson

@Ghadi
为了清楚起见...您用引号称呼它为“错误”。这似乎几乎不是一个错误。

但对我来说,这是一个足够真实的“bug”,我不得不选择使用分叉版本,或者完全放弃使用core.async。

我需要(<! (timeout 0))表示0,或者尽可能接近0。我需要它按预期工作。当前的实现并没有为0(或尽可能接近0)提供服务,相反,它提供了与(<! (timeout 4))相同的结果,与0ms(或尽可能接近0)相比,4ms是“永远”。以4ms的频率,goloop每秒只能迭代250次。

任何一个有goloop监听爆发式websocket输出的人都会遇到这个问题。他们需要疯狂处理(没有4ms延迟)但是也要交回控制权,以便浏览器可以做它需要的事情,时不时地。当浏览器页面失去“焦点”,进入后台,JavaScript被限制,动画帧变慢等情况发生时,所有这些问题都会加剧。

0
by

评论者:pkobrien

如果这有助于任何可能的读者,我已开始使用以下作为临时解决方案

`
(defn yield []
(let [ch (chan)]

(goog.async.nextTick #(close! ch))
ch))

(go
; 一些代码...
(<! (yield)) ;; 替代 (<! (timeout 0))
...)
`

0
by

评论者:mikethompson

这很好!确实提供了一个占位符解决方案。

0
by

评论者:mikethompson

在与halgari进一步讨论后,我认为应该将其关闭为“不会修复”(我无法找到如何关闭)。

https://www.reddit.com/r/Clojure/comments/5aprn3/in_coreasync_using_timeout_with_0_delay_causes_a/

0
by
参考:https://clojure.atlassian.net/browse/ASYNC-137(由mikethompson报告)
...