在 Clojure 中什么时候使用 core.async?

When to use core.async in Clojure?

我什么时候应该使用 Clojure 的 core.async 库,什么样的应用程序需要那种 async 东西?

Clojure 提供了 4 种基本可变模型,如 refsagentsatoms线程locals/vars。这些可变引用不能以任何方式轻松提供 core.async 提供的内容吗?

您能否提供 异步编程 的真实用例?

我怎样才能理解它,以便当我看到问题时,它会点击并说 "This is the place I should apply core.async"?

我们还可以在单​​线程环境ClojureScript中使用core.async,那有什么好处(除了避免回调地狱)?

你不妨看看这个:

core.async 的最佳用例是 ClojureScript,因为它允许您模拟 multi-threaded 编程并避免 回调地狱

在 JVM Clojure 中,core.async 也可以在您需要(轻量级)producer-consumer 架构的地方派上用场。当然,您也可以随时 use native Java queues

我发现它对 fine-grained 很有用,可配置控制 JVM 上的 side-effect 并行性。

例如如果以下执行从 Cassandra 读取,返回 async/chan:

(arche.async/execute connection :key {:values {:id "1"}})

然后下面执行一系列并行执行,其中并行度是可配置的,并返回结果in-order。

(async/pipeline-async
    n-parallelism
    out
    #(arche/execute connection :key {:values %1 :channel %2})
    (async/to-chan [{:id "1"} {:id "2"} {:id "3"} ... ]))

可能对我的利基市场来说很特别,但你明白了。

Core.async 为类似套接字的编程提供构建块,这对于协调 Clojure 中的 producer/consumer 交互非常有用。 Core.async 的轻量级线程(go 块)让您可以编写从通道读取的命令式代码,而不是在浏览器中使用回调。在 JVM 上,轻量级线程可让您充分利用 CPU 个线程。

您可以在此处查看 full-stack CLJ/CLJS producer/consumer Core.async 聊天室的示例:https://github.com/briangorman/hablamos

core.async 的另一个杀手级功能是管道功能。通常在数据处理中,初始处理阶段会占用大部分 CPU 时间,而后期阶段例如减少将显着减少。借助异步管道功能,您可以拆分多个通道的处理,以将并行化添加到您的管道中。 Core.async 通道与换能器一起工作,因此通道现在可以很好地与其他语言一起使用。

需要指出的是,'async' 这个词在编程圈中有两个常见的含义:

  1. 异步消息传递: 组件在不期望消费者响应的情况下发送消息的系统,通常甚至不知道消费者是谁(通过队列)
  2. non-blocking (a.k.a event-driven) I/O: 以不阻塞的方式构建程序等待响应时使用昂贵的计算资源(线程、核心等)。有几种抽象级别不同的方法来处理此类系统:callback-based API(low-level,难以管理,因为基于 side-effects), Promise/Futures/Deferreds(我们还没有的值的表示,更易于管理,因为它们是 value-based),Green Threads('logical' 模拟普通控制流的线程,但价格低廉)

core.async 对 1(通过队列的异步消息传递)非常有意见,并提供了一个用于实现绿色线程的宏(go 宏)。

根据我的经验,如果 non-blocking 是您所需要的全部,我个人建议从 Manifold, which makes fewer assumptions about your use case, then use core.async 开始,因为它不够先进;请注意,这两个库可以很好地互操作。