在<"+" https://www.surveymonkey.com/r/clojure2024">2024 Clojure状态调查中分享你的想法!

欢迎!请参阅关于页面以获取更多关于这是如何工作的信息。

0
core.async

目前,在现代浏览器中,(<! (timeout 0))将花费大约4ms,因为它最终变成(js/setTimeout f 0)。即使在时间段设置为0的情况下,现代浏览器中的setTimeout也不会在4ms内返回,而这对于只想将控制权退还给浏览器以最短的时间来说太久了。

参见
https://github.com/clojure/core.async/blob/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,但这正是我们试图避免在0ms持续时间内的问题。所以我看不到callOnce作为解决方案。

0

由: pkobrien 评论

我认为你是对的,Mike。尽管谷歌显然知道这个问题,但这很难相信。但现在我再读goog.Timer的代码,我看不出他们在那里修复了它。看起来goog.async.nextTick是唯一解决方案。

0
by

由: pkobrien 评论

此处只是想提到,这个问题适用于 ClojureScript 版本的 core.async,而且使用 (

0
by

评论者:gshayban

阅读这个“错误”报告后,似乎真正的问题是 CLJS 中的 goblock 分发更加多样。应该可以被改进,但是将 (

我们应该从根源上消除这个修复的需要,而不是使未定义的行为更加具体。ASYNC-131 和 ASYNC-43 是相关的,可能是更好的起点。

0
by

由:mikethompson 评论

@Ghadi
1. 我看不出来问题 131 与此有多大的关联,可以作为“更好的起点”。它们有不同的重点,代表不同的需求,并且可能会有不同的解决方案(正如当前的建议所示)。

  1. 在某种程度上,问题 43 似乎可以通过 David Nolen 指出的 Google Closure 分发方式关闭。顺便说一句,你会注意到我的建议是确实使用 goog.async.nextTick(因此我遵循 Google Closure 方法)。

此外,我不同意你的观点,认为 (

0
by

由:mikethompson 评论

@Ghadi
为了明确起见...你用引号将此称为“错误”。几乎好像它不是一个错误。

但我认为这是一个足够真实的“错误”,我必须要么用分支处理,要么完全改用 core.async。

我需要(<! (timeout 0))意味着0,或者尽可能接近0。我需要它按照宣传的那样工作。当前实现没有达到0(或尽可能接近0),而是得到(<! (timeout 4))和4ms与0ms(或接近它)相比是永恒的。以每个循环4ms,goloop每秒只能迭代250次。

任何有goloop监听爆发式WebSocket输出的人都会有这个问题。他们需要疯狂处理(没有4ms延迟),但同时也需要交回控制让浏览器做它需要的事情,偶尔一次。当浏览器页面失去“焦点”,进入后台,js被节流、动画帧减慢等时,所有这些问题都会加剧。

0

由: pkobrien 评论

如果对阅读此内容的人有帮助,我开始使用以下作为临时解决方案

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

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

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

0

由:mikethompson 评论

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

0

由:mikethompson 评论

在与halgari进一步讨论后,我相信这应该被关闭为“不会修复”(我无法找到如何关闭的方法)。

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

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