写点什么

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

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

关注

评论

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

SpringBoot 实战:JUnit5+MockMvc+Mockito 做好单元测试

看山

Java Spring Boot Effective Spring 10月月更

Mock Service Worker:可用于浏览器的Mock服务

devpoint

Vue Mock msw 10月月更

链路层的封装成帧和透明传输基本问题

Regan Yue

计算机网络 10月月更

CSS架构之Acss层

Augus

CSS 10月月更

【Flutter 专题】29 图解自定义底部状态栏 ACEBottomNavigationBar (一)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 10月月更

阿里P8高级架构师开发高并发系统经验总结

Java 程序员 架构 面试 后端

linux之sudo使用技巧汇总

入门小站

Linux

架构实战营_模块六作业_拆分电商系统为微服务

Rabbit

为何实现碳中和已刻不容缓?

CECBC

【Vuex 源码学习】第十三篇 - Vuex 辅助函数的实现

Brave

源码 vuex 10月月更

每个数据工程师都应该知道的 6 个 SQL 查询

云原生

sql 职业生涯 数据工程师

Vue进阶(幺叁陆):el-steps 实现页面内导航

No Silver Bullet

Vue 10月月更

听首歌的时间,简单复习下 python 网络编程之 socket,美不美?滚雪球学python第4季14篇

梦想橡皮擦

10月月更

Prometheus 基本查询(二)时序数据的瞬时向量

耳东@Erdong

Prometheus 10月月更

生命中不重要的九件事情

石云升

10月月更

绿色电力交易是一场迫在眉睫,区块链记录每一笔绿色电力交易

CECBC

区块链与智能革命的未来

CECBC

ThreadPoolExecutor学习笔记

风翱

ThreadPoolExecutor 10月月更

【Android构建新工具】Bazel构建工具介绍

轻口味

android 构建工具 10月月更

架构实战营模块5课后作业

apple

微博评论高性能高可用计算架构

刘琦Logan

【LeetCode】 山峰数组的顶部Java题解

Albert

算法 LeetCode 10月月更

真香!肝完Alibaba这份面试通关宝典,我成功拿下今年第15个Offer

收到请回复

Java 面试 大厂Offer 20+大厂面经

架构实战营 - 模块五作业

Alex.Wu

千万级学生管理系统的考试试卷存储方案

刘琦Logan

在线最大公因数计算器

入门小站

工具

架构实战营 - 模块五作业

en

#架构实战营

阿里内部教程:千页Redis源码笔记,涨薪必备

Java 程序员 架构 面试 后端

Go 中 Nil 理论上有类型,实践中无类型

baiyutang

golang 10月月更

Leetcode 题目解析:287. 寻找重复数

程序员架构进阶

算法 LeetCode 10月月更

016云原生之安全技术

穿过生命散发芬芳

云原生 10月月更

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