写点什么

core.async: 另一种 Clojure 和 ClojureScript 异步编程方式

  • 2013-07-28
  • 本文字数:1350 字

    阅读完需:约 4 分钟

虽然 core.async Clojure/ClojureScript 库发布还不到一个月,但是与此相关的博客帖子已经发布了很多,它们描述了如何有效地使用 core.async 在前端代码中避免“回调嵌套”,还展示了一些令人印象深刻的浏览器示例的简单代码

core.async 是一个用 Clojure 编写的,Clojure 和 ClojureScript 都能使用的库。Clojure 是一个基于 JVM 的 Lisp 实现。ClojureScript 是 Clojure 的一个子集,它可以将 Clojure 编译成 JavaScript。core.async 很好地呈现了 Lisp 所必须提供的宏机制的能力:很多其他的语言要实现 core.async 所做的事情必须要对语言做出改变,但是在一个 Lisp 中则可以通过使用的库来实现。

正如名字所提示的,core.async 是为了简化异步编程而设计的。它借鉴了 Go 语言的很多思想,特别是它的 goroutine (在 core.async 中称为 go blocks)和通道理念。一个通道是一个有一个或者多个发布者和一个或者多个消费者的队列。它的原理很简单:发布者将数据放到队列中,消费者从队列中获取数据。在 Clojure/ClojureScript 中数据是不可变的,通道提供了一种安全的方式在线程间通信。但是在 ClojureScript 中后者并不是一个特别有趣的特性,因为 JavaScript 是单线程的。

core.async 提供了两种方式向通道写入或者从通道读取数据:阻塞式和非阻塞式。一个阻塞写操作会阻塞线程,直到通道有空间被写入时为止(一个通道的缓冲区大小是可配置的);一个阻塞读操作会阻塞线程,直到队列中的值能够被读取到时为止。更有趣的是,ClojureScript 仅支持异步的通道读取和写入,并且这仅在“go 语句块”中才被允许。Go 语句块是按照同步风格编写的,在内部这些语句块会被转换成一个能够异步执行它们的状态机。

想想下面这段基于 core.async 的代码:

复制代码
(let [ch (chan)]
(go (while true
(let [v (<! ch)]
(println "Read: " v))))
(go (>! ch "hi")
(<! (timeout 5000))
(>! ch "there")))

在这个示例中,let 引入了一个新的局部变量 ch,它是一个新通道。在 let 域中定义了两个 go 语句块,第一个是一个永久循环,它从通道 ch 中读取(<!)一个新的值赋给变量 v。然后它会把“Read:”和读取到的值打印到标准输出。第二个 go 语句块向通道 ch:”hi”中写入(>!)两个值,然后它会等待 5 秒钟再向通道中写入“there”。等待 5 秒钟是通过一个 timeout 通道实现的,该通道会在设置的超时时间过后关闭自己(返回 nil)。在 Clojure REPL 中运行这段代码时,它会立即返回。然后它将打印“Read:hi”,5 秒钟之后它会打印“Read:there”。

无论哪个 JavaScript 程序员,在看到这个 while 循环的时候都会感到怪异:你不能这样实现阻塞循环:浏览器将会冻结 5 秒钟。core.async 的“魔力”在于,它会在内部将每一个 go 语句块的主体部分转换成一个状态机,并且将同步通道的读写转变成异步调用。如果你想获取 core.async 相关的更多信息,或者了解它对前端 Web 开发有什么影响,可以查看下面的资源:

查看英文原文 core.async: A Different Approach to Asynchronous Programming with Clojure and ClojureScript

2013-07-28 03:576051
用户头像

发布了 321 篇内容, 共 122.6 次阅读, 收获喜欢 19 次。

关注

评论

发布
暂无评论
发现更多内容

第七周作业

腾志文(清样)

操作系统、性能优化

GalaxyCreater

性能优化

架构师训练营 No.7 周作业

连增申

并发测试JAVA

王麒宇

第七周总结

上山砍柴

第七周学习总结

潜默闻雨

Vue3-组合式API

福豆粑粑

Vue3

第7周 性能优化:性能优化是架构师展现自己技术全面性的时刻

陆不得

架构师训练营 No.7 周总结

连增申

第7周

Geek_2b3614

ARTS打卡Week 08

teoking

ios LeetCode

Python 实现 RabbitMQ 的六种工作模式(附 Python 代码)

AlwaysBeta

Python RabbitMQ 消息队列

【架构师训练营 - week7 -1】作业

早睡早起

性能测试并发压力变大,系统如何变化

李朋

架构师训练营第七章作业

吴吴

Week 07 总结

鱼_XueTr

第07周 优化系统性能-01 学习总结

Jaye

第七周总结

腾志文(清样)

RabbitMQ 的监控(附 Python 监控源码)

AlwaysBeta

Python RabbitMQ 消息队列 消息堆积处理

架构师培训 -07 总结 性能测试与性能优化

刘敏

学习总结 - 架构师训练营 - 第七周

走过路过飞过

架构师 0期07周总结

我在终点等你

架构师训练营 - 作业 7

进击的炮灰

关于性能压测

俊俊哥

性能测试

Mac 环境下 RabbitMQ 的安装

AlwaysBeta

Mac RabbitMQ 消息队列

w7-分布式系统中性能的影响因素

麻辣

架构师训练营第七周总结

Bruce Xiong

【架构师训练营 - week7 -1】总结

早睡早起

week 7 作业

Geek_z9dmvw

架构师训练营 week7

devfan

第07周 优化系统性能-01 命题作业

Jaye

core.async: 另一种Clojure和ClojureScript异步编程方式_语言 & 开发_Zef Hemel_InfoQ精选文章