【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

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:575813
用户头像

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

关注

评论

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

dubbo-go 中如何实现路由策略功能

joe

Apache 开源 微服务 dubbo Go 语言

Nginx代理Oracle数据库连接

遇见

MySQL nginx oracle 反向代理

Facebook在用户增长到5亿时的扩容策略

Rayjun

团队管理 扩容

太慢是不行的

池建强

创业 产品

常用手机软件清单

彭宏豪95

效率工具 App 手机 移动应用

Disruptor为何这么快

Rayjun

Java Disruptor

终极 Shell

池建强

Linux Shell

用python爬虫保存美国农业部网站上的水果图片

遇见

Python GitHub 爬虫

关于HSTS - 强制浏览器使用HTTPS与服务器创建连接

遇见

https 安全 浏览器 TLS 证书

【SpringBoot】为什么我的定时任务不执行?

遇见

Java Spring Boot 定时任务 debug

软件工程的史前时代 -- Therac-25 事件

王泰

质量管理 软件工程 软件危机 软件测试

写作平台使用感受

小天同学

产品 体验 反馈

最近的一些人生感悟

小智

人生 哲学

过滤数组中重复元素,你知道最优方案吗?

麦洛

数据结构 数组 数组去重

像经营咖啡店一样扩容 Web 系统

Rayjun

Web 扩容

理性主义和实证主义

王泰

理性主义 实证主义 哲学 软件工程

死磕Java并发编程(6):从源码分析清楚AQS

Seven七哥

Java Java并发 并发编程 AQS

回"疫"录(1):口罩危机也许是一种进步

小天同学

疫情 回忆录 现实纪录

个人知识管理精进指南

非著名程序员

学习 读书笔记 知识管理 认知提升

【SpringBoot】为什么我的 CommandLineRunner 不 run ?

遇见

Java Spring Boot

回"疫"录(2):不知者无畏

小天同学

疫情 回忆录 现实纪录

死磕Java并发编程(3):volatile关键字不了解的赶紧看看

Seven七哥

Java Java并发 volatile

有关Kotlin Companion 我们需要了解到的几个知识点

王泰

Java 编程 kotlin 编程语言

敏捷(组织)转型的6个准备条件

Bob Jiang

团队管理 敏捷 组织转型

揭秘|为何程序员们能一直保持高收入?

丁长老

学习 程序员 写作 高薪

软件世界中的个人英雄与团队协作

王泰

团队管理 软件工程 团队协作

Zoom的加密算法,到底有什么问题?

X.F

算法 编码习惯 产品设计 安全 编程语言

程序员陪娃看绘本之启示

孙苏勇

程序员 生活 读书 成长 陪伴

【SpringBoot】给你的 CommandLineRunner 排个序

遇见

Java Spring Boot

如何画一个闹钟

池建强

视觉笔记

我敢说 80% 的程序员都掉进了「老鼠赛跑」的陷阱

非著名程序员

读书笔记 程序员 程序人生 提升认知

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