简介通信顺序进程CSP的7个示例是什么?通俗的说就是一套写并行代码的方案。这个功能是Go语言自带的,Clojure是通过Macro-basedcore.async来实现的,现在JavaScript也通过Generator来实现,可以做支持,或者ES6的功能。我为什么要关心CSP?因为它强大、高效且简单。你还想要什么?:)好吧,让我们谈谈细节。如何使用它?我们使用js-csp,需要生成器支持,只有ES6才有。也就是说Node4或者更高版本就可以了,或者浏览器代码可以用Babel编译,当然其他的编译工具也可以,但是你要确认下是支持Generator的。注:文章写得较早。现在正在翻译文章,Chrome应该支持Generator。让我们看一个例子!示例1:过程要学习的第一个概念是“过程”。进程可以执行代码,简单来说就是这样。:)注意:当然不是操作系统原有的进程,是js中模拟出来的。这是启动进程的语法:生成器函数作为参数,传递给go函数执行。import{go}from'js-csp';go(function*(){console.log('something!');});//terminaloutput:////=>something!例子2:使用yield键可以暂停进程单词可以暂停一个进程,释放当前进程的占用:import{go,timeout}from'js-csp';go(function*(){yieldtimeout(1000);console.log('somethingelseafter1second!');});console.log('something!');//终端输出:////=>something!//=>somethingelseafter1second!例3:进程等待管道的数据第二个要学习的概念是管道,也是**一个。管道就像一个队列。一旦流程调用接管管道,流程将暂停,直到其他人将数据放入管道。import{go,chan,take,putAsync}from'js-csp';letch=chan();go(function*(){constreceived=yieldtake(ch);console.log('RECEIVED:',received);});consttext='something';console.log('SENDING:',text);//useputAsynctoputavalueina//channelfromoutsideaprocessputAsync(ch,text);//terminaloutput:////=>SENDING:something//=>RECEIVED:som??ethingExample4:进程通过管道与管道的另一端进行通信,那些往管道中放入数据的进程也会暂停,直到进程调用到这里为止。下面的例子稍微复杂一点,试试看主线,确认一下终端输出内容:import{go,chan,take,put}from'js-csp';letchA=chan();letchB=chan();//ProcessAgo(function*(){constreceivedFirst=yieldtake(chA);console.log('A>RECEIVED:',receivedFirst);constsending='cat';console.log('A>SENDING:',发送);yieldput(chB,sending);constreceivedSecond=yieldtake(chA);console.log('A>RECEIVED:',receivedSecond);});//ProcessBgo(function*(){constsendingFirst='dog';console.log('B>SENDING:',sendingFirst);yieldput(chA,sendingFirst);constreceived=yieldtake(chB);console.log('B>RECEIVED:',received);constsendingSecond='anotherdog';console.log('B>SENDING:',sendingSecond);yieldput(chA,sendingSecond);});//terminaloutput:////=>B>SENDING:dog//=>A>RECEIVED:dog//=>A>SENDING:cat//=>B>RECEIVED:cat//=>B>SENDING:anotherdog//=>A>RECEIVED:anotherdog例5:管道也是一个队列因为管道是一个队列,当进程从管道中取数据,其他进程取不到。所以推数据的是一个进程,取数据的也是一个进程。在下面的示例中,您可以看到第二个进程永远不会打印B>RECEIVED:dog,因为***该进程已将data.import{go,chan,take,put}from'js-csp';letch=chan();go(function*(){consttext=yieldtake(ch);console.log('A>RECEIVED:',text);});go(function*(){consttext=yieldtake(ch);console.log('B>RECEIVED:',text);});go(function*(){consttext='dog'console.log('C>SENDING:',text);yieldput(ch,text);});//terminaloutput:////=>C>SENDING:dog//=>A>RECEIVED:dog例6:缓冲管道在put操作过程中不会阻塞管道可以缓冲,即put操作可以避免阻塞一定量的数据。在这个例子中,即使没有其他进程调用take,前两次写操作也不会阻塞进程。但是管道中缓存的个数是2,所以第三个数据会阻塞进程,直到其他进程拿走数据。import{go,chan,put,buffers}from'js-csp';letch=chan(buffers.fixed(2));go(函数*(){yieldput(ch,'valueA');yieldput(ch,'valueB');console.log('Ishouldprint!');yieldput(ch,'valueC');console.log('Ishouldnotprint!');});//terminaloutput:////=>Ishouldprint!实例7:拖放和滑动缓冲区固定大小的缓冲区会在N个数据后阻塞,除了第一次,缓冲区上还有拖放和滑动控件。删除缓冲区意味着管道可以容纳N个数据。将额外的数据添加到管道中,管道将丢弃它。缓冲滑动也可以保存N个数据。不过相比于直接丢弃新数据,滑动缓冲会将原来*最先推送的数据丢弃,新数据会留在缓冲区中。在下面的示例中,值B和值C在丢弃缓冲区中被丢弃,因为已经存在值A。在第二个过程中,当值B被放入管道时,值A被丢弃。然后值C被放入管道,值B被丢弃。根据它们的工作原理,下降和滑动的缓冲区是永远不会阻塞的!letdroppingCh=chan(buffers.dropping(1));letslidingCh=chan(buffers.sliding(1));go(function*(){yieldput(droppingCh,'valueA');yieldput(droppingCh,'valueB');yieldput(droppingCh,'valueC');console.log('DROPPING:',yieldtake(droppingCh));});go(function*(){yieldput(slidingCh,'valueA');yieldput(slidingCh,'valueB');yieldput(slidingCh,'valueC');console.log('SLIDING:',yieldtake(slidingCh));});//终端output:////=>DROPPING:valueA//=>SLIDING:valueC结语使用CSP一段时间后,用callback或者Promise写代码就像侏罗纪科技。我希望ES6Generator可以帮助CSP成为JavaScript的标准,就像Go已经是,Clojure正在成为的那样。接下来,还有另外两个模型也很有意思,可以认为比CSP高一点:函数式和反应式编程(Rx)和Actor分别在Rx和Erlang中使用。当然后面会写博客去挖掘。我也相信CSP非常适合前端框架。
