资讯专栏INFORMATION COLUMN

js-csp 可以开始尝试了

tracymac7 / 2156人阅读

摘要:的用例的用法最早是语言传开来的看一下我从网上扒的代码其中符号是往当中写入数据的操作同时注意一般的位置对于来说是阻塞的由于能够处理异步操作也就是说能做到异步代码用同步写法更多的细节搜索应该就能找到除了也实现了对于的支持也就是

CSP 的用例

CSP 的用法最早是 Go 语言传开来的, 看一下我从网上扒的代码:

package main

import "fmt"

func ping(pings chan<- string, msg string) {
    pings <- msg
}

func pong(pings <-chan string, pongs chan<- string) {
    msg := <-pings
    pongs <- msg
}

func main() {
    pings := make(chan string, 1)
    pongs := make(chan string, 1)
    ping(pings, "passed message")
    pong(pings, pongs)
    fmt.Println(<-pongs)
}

其中 <- 符号是往 channel 当中写入数据的操作.
同时注意一般 <- 的位置对于 goroutine 来说是阻塞的,
由于 channel 能够处理异步操作, 也就是说能做到异步代码用同步写法.
更多的细节搜索 "go channel" 应该就能找到.

除了 Go, Clojure 也实现了对于 CSP 的支持, 也就是 core.async 这个库,
在 Clojure 当中语法做了调整, 成了 >! 这样的写法, 有点怪,
但是基本功能差不多, >! 都是模仿的阻塞, channel 概念也一样:

(let [c1 (chan)
      c2 (chan)]
  (go (while true
        (let [[v ch] (alts! [c1 c2])]
          (println "Read" v "from" ch))))
  (go (>! c1 "hi"))
  (go (>! c2 "there")))

这个例子当中 (chan) 生成 channel, 然后用 go 生成 3 个线索...
虽然用了 while true, 但是通过 alts! 也形成了阻塞.
更新细节搜索 "core.async" 可以找到.

为什么用 CSP

看 Wiki https://en.wikipedia.org/wiki...

In computer science, communicating sequential processes (CSP) is a formal language for describing patterns of interaction in concurrent systems.[1] It is a member of the family of mathematical theories of concurrency known as process algebras, or process calculi, based on message passing via channels. CSP was highly influential in the design of the occam programming language,1 and also influenced the design of programming languages such as Limbo[3] and Go.[4]

CSP 本来是用于描述并发的系统之间如何交互的, 也就是在 Go 当中的用法.
由于并发的操作通常都是异步的, 所以 CSP 也能适合异步的行为.
最主要的概念就是 Channel, 也叫做"管道", Channel 可以用于传输数据,
因而就有对于管道读和写的操作, 分别是 take!put!, Clojure 里的叫法.
前面说了, 管道看上去是阻塞代码执行的, 也就是说读和写可以进行等待.
这样就能模拟一些场景, 比如抓取网络数据再打印, 就很容易写出来了.

常见功能还有 alts!, 对应 Go 的 select, 就是多个 Channel 取首先返回的数据,
还有 merge 记不大清, 好像是汇总多个 Channel 返回的数据, 变成一个?
其他的 filter, map 等等序列的操作, 在 Channel 上也有类似实行,
另一方面 CSP 在实用当中应该是进行了扩展, 实际功能不止这些.
比如说增加了 (timeout 1000) 这样的 Channel 等待一秒返回数据,
还有对 Channel 进行 Buffer 的功能, 以及异步的推数据等等.

听起来很花哨, 但是如果有动画可以展示一下就很清楚了, 我还没找到...
从整体的思路上说, 这是对于异步事件的一种抽象, 可以用来实现很多业务.
想想办法再解释细节吧, 我这里先介绍 JavaScript 这边的情况...

js-csp 的现状

由于 Node 6 开始有 yield, 用同步代码写异步成为了可能,
于是有就有了 js-csp 这个模块, 通过 yield 实现了 CSP 的功能,
我还看到一个用了 async 的, 估计不能用, 但是供参考:

https://github.com/ubolonton/...
https://github.com/dvlsg/asyn...

我直接贴一遍 README 当中的例子, 自己看看能不能看懂:

function* player(name, table) {
  while (true) {
    var ball = yield csp.take(table); // 等待取得数据
    if (ball === csp.CLOSED) { // 关闭状态特殊处理
      console.log(name + ": table"s gone");
      return;
    }
    ball.hits += 1;
    console.log(name + " " + ball.hits);
    yield csp.timeout(100); // 等待延时结束
    yield csp.put(table, ball); // 推数据并等待对方取
  }
}

csp.go(function* () {
  var table = csp.chan(); // 创建 Channel

  csp.go(player, ["ping", table]); // 相当于启动 goroutine
  csp.go(player, ["pong", table]); // 相当于启动 goroutine

  yield csp.put(table, {hits: 0}); // 推数据等待对方取
  yield csp.timeout(1000); // 等待延时结束
  table.close();
});

运行的效果是:

=>> node go.js
ping 1
pong 2
ping 3
pong 4
ping 5
pong 6
ping 7
pong 8
ping 9
pong 10
ping: table"s gone
pong: table"s gone

这样模拟的就是两个进程之间相互发送数据的场景.

但实际上 CSP 可以对事件流进行抽象, 也就能做出更强大的功能.
这就是在我之前推荐的这篇文章上的做的介绍, 点进去看吧:
http://jlongster.com/Taming-t...

随着浏览器和 Node 对 yield 支持的完善, 使用 js-csp 已经可以做到.
考虑到方案的灵活性, 我认为值得往深了去挖一挖.

和 Rx 的对比

事件流的另一套有名的方案就是 Rx, 有 js 版本的 Rxjs.
大概来说, Rx 是用 OOP 语法封装的 FP 风格的响应式编程方案, 操作繁多,
而 CSP 通过管道提供的是一些灵活但过于基础的原语,
看社区的讨论, 其实有很大的重叠的部分, 尽管细节还很难说...
我搜集了一些文章:

https://medium.com/@puppybits...

还有 GitHub 上的一些讨论:

https://github.com/ubolonton/...
https://github.com/cyclejs/cy...

另外还有某人用 Rx 写法模仿 CSP 方案的博客:

http://swannodette.github.io/...
http://swannodette.github.io/...
http://potetm.github.io/2014/...
http://potetm.github.io/2014/...

小结

说起来我还没怎么消化这东西.. 但是如果看过文章里的 Demo, 你一定印象深刻,
流是数据和时间绑定在一起形成的产物, 普通的编程手法很难处理,
但是 CSP 的概念让处理 Channel 中传递的数据成为了而比较灵活的事情.
参考国外社区的评论, 这是具备相当大价值的一块知识, 所以在持续跟进.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90935.html

相关文章

  • js-csp 异步编程的一些简单的例子

    摘要:发现一个月没刷技术文章了有点慌整理一篇短的用法出来只包含最基本的用法在里边最清晰不过我是在写的版本的实现包含异步用法会更繁琐一些但是也值得看看我相信普及之前还是一个很有意思的选择我的代码写的是可以自动脑补圆括号花括号上去注意包含的函数自动 发现一个月没刷技术文章了, 有点慌, 整理一篇短的 CSP 用法出来,只包含最基本的用法, 在 Go 里边最清晰, 不过我是在 Clojure 写的...

    curried 评论0 收藏0
  • [译] 快速介绍 JavaScript 中的 CSP

    摘要:原文的个示例是什么一般来说它是写并行代码的一套方案在语言里自带该功能通过基于的来实现现在通过也能做支持了或者说的功能为什么我要关心因为它强大啊而且高效而且简单都这样了你还想要什么好吧说细节怎样使用呢我们用而且需要支持才有也就说或者更高的版 原文 http://lucasmreis.github.io/b... Communicating Sequential Processes 的 7...

    Rocko 评论0 收藏0
  • React 组件之间如何交流

    摘要:前言今天群里面有很多都在问关于组件之间是如何通信的问题,之前自己写的时候也遇到过这类问题。英文能力有限,如果有不对的地方请跟我留言,一定修改原著序处理组件之间的交流方式,主要取决于组件之间的关系,然而这些关系的约定人就是你。 前言 今天群里面有很多都在问关于 React 组件之间是如何通信的问题,之前自己写的时候也遇到过这类问题。下面是我看到的一篇不错英文版的翻译,看过我博客的人都知道...

    tomlingtm 评论0 收藏0
  • ES6 Generator实现协同程序

    摘要:关键字表示代码在该处将会被阻塞式暂停阻塞的仅仅是函数代码本身,而不是整个程序,但是这并没有引起函数内部自顶向下代码的丝毫改变。通过实现模式在通过实现理论的过程中已经有一些有趣的探索了。 至此本系列的四篇文章翻译完结,查看完整系列请移步blogs 由于个人能力知识有限,翻译过程中难免有纰漏和错误,望不吝指正issue ES6 Generators: 完整系列 The Basics...

    MudOnTire 评论0 收藏0

发表评论

0条评论

tracymac7

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<