文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何理解JavaScript中的CSP

2024-04-02 19:55

关注

如何理解JavaScript中的CSP,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

Communicating Sequential Processes 的 7 个示例

CSP 是什么? 一般来说, 它是写并行代码的一套方案.

在 Go 语言里自带该功能, Clojure 通过基于 Macro 的 core.async 来实现,

现在 JavaScript 通过 Generator 也能做支持了, 或者说 ES6 的功能.

为什么我要关心 CSP? 因为它强大啊, 而且高效, 而且简单. 都这样了你还想要什么? :)

好吧, 说细节. 怎样使用呢?我们用 js-csp, 而且需要 generator 支持, ES6 才有.

也就说 Node 4 或者更高的版本才行, 或者浏览器代码用 Babel 编译一下,

当然能其他的编译工具可能也行, 但你要确认下是支持 Generator 的.

Chrome 应该是支持 Generator 的.

扯多了, 来看例子吧!

例 1: 进程

***个要学的概念是"进程". 进程可以执行代码, 简单说就是这样的了. :)

注: 当然不是操作系统原始的进程了, js 里模拟的.

这是启动进程的语法: generator 函数作为参数, 传给 go 函数执行.

import {go} from 'js-csp';  go(function* () {   console.log('something!'); });  // terminal output: // // => something!

例 2: 进程可以暂停

使用 yield 关键字可以暂停一个进程, 把当前进程的占用释放:

import {go, timeout} from 'js-csp';  go(function* () {   yield timeout(1000);   console.log('something else after 1 second!'); });  console.log('something!');  // terminal output: // // => something! // => something else after 1 second!

例 3: 进程等待来自管道的数据

第二个要学的概念是管道, 也是***一个了. 管道就像是队列.

一旦进程对管道调用 take, 进程就会暂停, 直到别人往管道放进数据.

import {go, chan, take, putAsync} from 'js-csp';  let ch = chan();  go(function* () {   const received = yield take(ch);   console.log('RECEIVED:', received); });  const text = 'something'; console.log('SENDING:', text);  // use putAsync to put a value in a // channel from outside a process putAsync(ch, text);  // terminal output: // // => SENDING: something // => RECEIVED: something

例 4: 进程通过管道来通信

管道的另一边, 往管道里 put 数据的那些进程也会暂停, 直到这边进程调用 take.

下面的例子就复杂一点了, 试着跟随一下主线, 印证一下终端输出的内容:

import {go, chan, take, put} from 'js-csp';  let chA = chan(); let chB = chan();  // Process A go(function* () {   const receivedFirst = yield take(chA);   console.log('A > RECEIVED:', receivedFirst);    const sending = 'cat';   console.log('A > SENDING:', sending);   yield put(chB, sending);    const receivedSecond = yield take(chA);   console.log('A > RECEIVED:', receivedSecond); });  // Process B go(function* () {   const sendingFirst = 'dog';   console.log('B > SENDING:', sendingFirst);   yield put(chA, sendingFirst);    const received = yield take(chB);   console.log('B > RECEIVED:', received);    const sendingSecond = 'another dog';   console.log('B > SENDING:', sendingSecond);   yield put(chA, sendingSecond); });  // terminal output: // // => B > SENDING: dog // => A > RECEIVED: dog // => A > SENDING: cat // => B > RECEIVED: cat // => B > SENDING: another dog // => A > RECEIVED: another dog

例5: 管道也是队列

由于管道是队列, 当进程从管道取走数据, 其他进程就拿不到了.所以推数据的是一个进程, 取数据的也是一个进程.

下面这个例子可以看到第二个进程永远不会打印 B > RECEIVED: dog,

因为***个进程已经把数据取走了.

import {go, chan, take, put} from 'js-csp';  let ch = chan();  go(function* () {   const text = yield take(ch);   console.log('A > RECEIVED:', text); });  go(function* () {   const text = yield take(ch);   console.log('B > RECEIVED:', text); });  go(function* () {   const text = 'dog'   console.log('C > SENDING:', text);   yield put(ch, text); });  // terminal output: // // => C > SENDING: dog // => A > RECEIVED: dog

例 6: 带缓冲的管道不会在 put 操作时阻塞

管道可以带缓冲, 也就是, 一定数量之内的数据, 执行 put 操作可以避开阻塞.

这个例子里, 即便没有其他进程调用 take, 前两个写操作也不会阻塞进程.

不过管道的缓存数量是 2, 所以第三个数据就阻塞进程了, 直到其他进程取走数据.

import {go, chan, put, buffers} from 'js-csp';  let ch = chan(buffers.fixed(2));  go(function* () {   yield put(ch, 'value A');   yield put(ch, 'value B');   console.log('I should print!');   yield put(ch, 'value C');   console.log('I should not print!'); });  // terminal output: // // => I should print!

例 7: Dropping And Sliding Buffers

固定大小的缓冲在 N 个数据之后会阻塞, 初次之外, 还有对缓冲的 dropping 和 sliding 控制.

缓冲的 dropping 以为着管道可以持有 N 个数据.再增加额外的数据放进管道, 管道就会将其丢弃.

缓冲的 sliding 也可以持有 N 个数据. 不过相对于直接丢弃新数据,sliding 缓冲原先的***个推的数据会被丢弃, buffer  里会留下新的这个数据.

下面这个例子, value B 和 value C 在 dropping 缓冲里被丢弃, 因为已经有 value A 了.

第二个进程里, 当 value B 被放进管道, value A 就被丢弃了.

然后 value C 放进管道, value B 就被丢弃.

根据它们的工作原理, dropping 和 sliding 的缓冲永远不会阻塞!

let droppingCh = chan(buffers.dropping(1)); let slidingCh  = chan(buffers.sliding(1));  go(function* () {   yield put(droppingCh, 'value A');   yield put(droppingCh, 'value B');   yield put(droppingCh, 'value C');   console.log('DROPPING:', yield take(droppingCh)); });  go(function* () {   yield put(slidingCh, 'value A');   yield put(slidingCh, 'value B');   yield put(slidingCh, 'value C');   console.log('SLIDING:', yield take(slidingCh)); });  // terminal output: // // => DROPPING: value A // => SLIDING: value C

CSP 用了一段时间之后, 用回调或者 Promise 写代码就像是侏罗纪的技术.

我希望 ES6 的 Generator 能帮助 CSP 成为 JavaScript 的一个标准,

就像是 Go 已经是的那样, 以及 Clojure 里正在成为的那样.

另外有两个模型也还有意思, 大概可以认为是比 CSP 层级更高一点的:

函数式也是响应式编程(Rx)跟 Actors, 分别在 Rx 和 Erlang 里用到.

我同时相信 CSP 对于前端框架来说非常棒.

关于如何理解JavaScript中的CSP问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网行业资讯频道了解更多相关知识。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯