每周优秀代码赏析—Jscex内核【一】

一.简介

Jscex is JavaScript implementation of F#'s Computation Expressions.

image

它的灵感的源于F#,它为JavaScript语言提供了一个monadic扩展。Jscex完全使用JavaScript编写,能够在任意支 持ECMAScript 3的引擎里使用(例如各浏览器或Node.js)。Jscex的JIT编译器能在运行时将JavaScript代码编译成Monad形式,无需额外编译步 骤,并内置异步编程类库,可以大大简化JavaScript下的异步编程体验。

 

 

二.原理探析

先揭开Jscex 内核之前我们先体验一下世界上最简单的一个 Jscex例子:

       var i = 0;

       var countAsync = eval(Jscex.compile("async", function () {

           while (true) {

               i++;

               document.getElementById("show").innerHTML = i;

               $await(Jscex.Async.sleep(1000));

           }

       }))

       countAsync().start();

一个计数器,从0开始每秒钟加1并显示出来。

然后我们把countAsync  alert出来,看看Jscex把它compile成什么个样子:

function () {

    var $$_builder_$$_0 = Jscex.builders["async"];

    return $$_builder_$$_0.Start(this,

        $$_builder_$$_0.Loop(

            function () {

                return true;

            },

            null,

            $$_builder_$$_0.Delay(function () {

                i++;

                (document.getElementById("show")).innerHTML = i;

                return $$_builder_$$_0.Bind(Jscex.Async.sleep(1000), function () {

                    return $$_builder_$$_0.Normal();

                });

            }),

            false

        )

    );

}

一个匿名函数,然后用eval().start()执行该匿名函数。

那么上面还能拆开吗?如果作为一个纯粹的.NET或者JAVA程序员,看这段代码肯定很费劲,因为funciton里套funciton,return套return.

如果你知道javascript的执行顺序的话,上面的函数是还可以拆的:

        var count = 0;

        function doCount() {

            count++;

            document.getElementById("clock").innerHTML = count;

        }



        var $$_builder_$$_0 = Jscex.builders["async"];



        var delayCount = $$_builder_$$_0.Delay(function () {

            doCount();

            return $$_builder_$$_0.Bind(Jscex.Async.sleep("1000"), function () {

                return $$_builder_$$_0.Normal();

            });

        });



        var loopCount = $$_builder_$$_0.Loop(

            function () {

                return true;

            },

            null,

           delayCount,

            false

        );



        var countAsync = $$_builder_$$_0.Start(this, loopCount);

        

        countAsync.start();

这样视乎就很清楚它的执行顺序了~~~!

从上面的代码,我们可以看得出来:我们要做的事情就是:加1显示然后停一秒···加1显示然后停一秒····无限循环下去

我们发生的事情generator就是:

        var delayCount = $$_builder_$$_0.Delay(function () {

            doCount();

            return $$_builder_$$_0.Bind(Jscex.Async.sleep("1000"), function () {

                return $$_builder_$$_0.Normal();

            });

        });

我们要循环的就是delayCount,所以我们把它放到一个loop当中去:

        var loopCount = $$_builder_$$_0.Loop(

            function () {

                return true;

            },

            null,

           delayCount,

            false

        );

其中,第一个参数就是while(true),他标志这函数什么时候退出循环。所以比如while(i<3), 它就会编译成function(){return i<3;}

然后:

var countAsync = $$_builder_$$_0.Start(this, loopCount);

这行代码的主要作用是 把这个loop作为一个task赋给Jscex.Async.Task的_delegate,

可想而知,在这种架构的基础上,可以轻松实现N个loop,就有了异步队列~~~~

比如:

       var executeAsyncQueue = eval(Jscex.compile("async", function () {

           while (true) {

               $await(countAsync())

               $await(otherAsync())

               $await(Jscex.Async.sleep(1000));

           }



       }))

       executeAsyncQueue().start();

最后,执行countAsync ().start().整个流程就是这样子的,但是到现在为止,我们还没有进入Jscex内核当中去看一看它是怎么实现这些循环和中转的······

或者你根据上面的思路写出一个伪Jscex出来?我想这个写的过程可以帮你更好的理解Jscex的模式。

请关注:

每周优秀代码赏析—Jscex内核【二】

你可能感兴趣的:(js)