首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用core.async代替回调?

如何使用core.async代替回调?
EN

Stack Overflow用户
提问于 2018-12-24 09:34:12
回答 2查看 309关注 0票数 2

我在ClojureScript上使用core.async,以避免使用node.js回调。问题是我达到了1024条挂起消息的限制。

为了避免这种情况,我需要将所有消息发送到同一个go块中的通道。但这在core.async上是不可能的,因为匿名函数会使go的效果失效,所以我不能这样做:

代码语言:javascript
复制
(go
  (. socket on "data" #(>! chan %)))

那么,有没有办法绕过这个限制呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-12-30 11:00:26

为了模拟错误,我们可以“模拟”一种回调:

代码语言:javascript
复制
(let [callback (atom nil)
      on-data (fn [fun]
                (reset! callback fun))
      chan (async/chan)]

如果我们尝试使用(on-data #(async/go (async/put! chan %)))添加一个回调,它将超出限制。此外,当我们使用async/go时,它会导致通道中的消息顺序混乱。

我发现解决这个问题的唯一方法是在atom中创建一个无限的promise-chan列表,每次回调都会选取第一个元素,发布一条消息,然后删除该列表的第一个元素。然后,我们可以在go块中有一个doseq,它将为我们发布消息:

代码语言:javascript
复制
(let [inf-list (atom (map (fn [_] (async/promise-chan)) (range)))]
  ; We need to iterate over inf-list before anything
  (let [lst @inf-list]
    (async/go
     (doseq [c lst]
       (async/>! chan (async/<! c)))))

  (on-data #(do
              (async/put! (first @inf-list) %)
              (swap! inf-list rest))))
票数 0
EN

Stack Overflow用户

发布于 2018-12-24 15:09:28

我不确定我是否理解为什么它必须在同一个go块中。通常,您只需执行以下操作:

代码语言:javascript
复制
(. socket on "data" #(go (put! chan %)))

然后在另一个go块中处理chan

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53908423

复制
相关文章

相似问题

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