• Wind.js的一些简单使用和说明


    零零碎碎的看了一些关于wind(原名jscex)的说明和例子,其实也没太明白,这里写一些个人看法...

    wind.js,一个可以让你已同步方式编写代码异步执行的lib,可作用于前后端js环境...

    如何编写?

    var printAsync = eval(Wind.compile("async", function (text) {

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

      console.log(text);

      return text;
    }));

    定义一个wind方法要包装在eval(Wind.compile("async", …)中...

    var task = printAsync("Hello World");

    调用它后返回的是一个task对象,需要调用start方法执行

    tack.start();

    下面已浏览器为例,下载wind资源

    页面中依次引入

    <script src="wind-core.js" type="text/javascript"></script>
    <script src="wind-compiler.js" type="text/javascript"></script>
    <script src="wind-builderbase.js" type="text/javascript"></script>
    <script src="wind-async.js" type="text/javascript"></script>
    
    <script type="text/javascript">
    var printAsync = eval(Wind.compile("async", function (text) {
    $await(Wind.Async.sleep(1000));
    console.log(text);
    return "aaa";
    }));
    var task = printAsync("Hello World");
    task.start();
    console.log(task);
    </script>

    在浏览器控制台的打印结果...

    // Original: 
    
    function (text) {
                $await(Wind.Async.sleep(1000));
                console.log(text);
                return "aaa";
            }
    
    
    
    // Compiled: 
    
    /* async << function (text) { */   (function (text) {
                                           var _builder_$0 = Wind.builders["async"];
                                           return _builder_$0.Start(this,
                                               _builder_$0.Delay(function () {
    /*     $await(Wind.Async.sleep(1000)); */      return _builder_$0.Bind(Wind.Async.sleep(1000), function () {
    /*     console.log(text); */                       console.log(text);
    /*     return "aaa"; */                            return _builder_$0.Return("aaa");
                                                   });
                                               })
                                           );
    /* } */                            })
    //@ sourceURL=wind/0_anonymous.js
    
     wind-core.js:158
    Async.Task
    _delegate: function (t) {
    _eventManager: null
    _result: "aaa"
    status: "succeeded"
    __proto__: Object
     test.htm:19
    injectScript startLiveReload init
    Hello World 

    从打印注释可以看出wind把原来的方法编译成了自己需要的形式..

    同时也看到了我们自己打印的text值为Hello World和task对象结构..

    其中_result为我们返回的值,status为succeeded...

    我们写的函数里唯一不同的是用了$await(Wind.Async.sleep(1000));

    Wind.Async.sleep(1000)是wind自身为我们提供的,从意思可以看出来是停止1秒,它返回的是一个tesk对象...

    $await接受task类型参数,它等待此task执行结束并返回结果,如果此task没有启动就调用start启动执行...

    从这可以看出我们写的wind方法可以嵌套在另一个wind方法内,通过$await命令来执行并等待结果...

    例如

    var printAllAsync = eval(Wind.compile("async"function (texts) {

    for (var i = 0; i < texts.length; i++) {

    $await(printAsync(texts[i]));

    }

    }));

    当然它还提供了一些其他方法...但是这之前还是大体了一下它的结构和为什么会这样...

    wind现在主要提供了5个模块,从命名基本可以看出是干什么的...

    它的结构组织方式也比较好懂,建议从底到上阅读...

    为了更好的看出各模块的引用顺序,依赖说明和选项信息,这里已node环境为例...

    首先看wind-core.js

       if (isCommonJS) {
            Wind = module.exports;
            init();
        } else if (isAmd) {
            define("wind-core", function () {
                Wind = { };
                init();
                return Wind;
            });
        } else {
            // Get the global object.
            var Fn = Function, global = Fn('return this')();
        
            if (global.Wind) {
                throw new Error("There's already a Wind root here, please load the component only once.");
            }
            
            Wind = global.Wind = { };
            init();
        }

    每个模块底部都有这么一个东西,基本就是判断在哪种环境下,然后执行init初始,由于这里是node环境,所以每次只关注

    if (isCommonJS) {
            Wind = module.exports;
            init();
        } 

    这里即可..

    输出wind执行init函数

    var init = function () {
    Wind.logger = new Logger();
    Wind.Logging = {
    Logger: Logger,
    Level: Level
    };

    Wind._ = _;
    Wind.modules = { core: { name: "core", version: "0.7.0" } };
    Wind.binders = { };
    Wind.builders = { };
    Wind.define = defineModule;
    };

    给wind添加一个核心方法

    wind-compiler.js模块

    if (isCommonJS) {
    try {
    Wind = require("./wind-core");
    } catch (ex) {
    Wind = require("wind-core");
    }

    defineModule();
    }
    可以看到它会自动加载core,
    然后执行defineModule

    var defineModule = function () {
    Wind.define({
    name: "compiler",
    version: "0.7.1",
    require: isCommonJS && require,
    dependencies: { core: "~0.7.0" },
    init: function () {
    Wind.parse = parse;
    Wind.compile = compile;
    }
    });
    }

    这里看到了调用了wind的define方法.然后你跟进去就会发现,有autoloads就自动加载,有依赖就检测是否引用..主要就是执行init这里给wind对象又安插了parse和compile方法,主要就是靠它俩实现wind方法变成成正常方法...

     然后你每个模块的底部都看看就知道了

    wind-builderbase模块依赖core,wind-async和wind-promise都依赖wind-builderbase

    wind-builderbase提供了一些编译后的基本方法...

    下面看看wind-async中的代码...

    var defineModule = function () {
    Wind.define({
    name: "async",
    version: "0.7.0",
    require: isCommonJS && require,
    autoloads: [ "builderbase" ],
    dependencies: { builderbase: "~0.7.0" },
    init: function () {

    _ = Wind._;

    _.each(Wind.BuilderBase.prototype, function (m, fn) {
    AsyncBuilder.prototype[m] = fn;
    });

    Wind.Async = Async;

    Wind.binders["async"] = "$await";
    Wind.builders["async"] = new AsyncBuilder();
    }
    });
    }

     把BuilderBase的方法都安装到AsyncBuilder中..

     从这里可以看出Wind.binders["async"] = "$await";
    Wind.builders["async"] = new AsyncBuilder();

     之前写的

    var printAsync = eval(Wind.compile("async", function (text) {

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

      console.log(text);

      return text;
    }));

    async和await应该都是这里定义的...

    从前面打印的结果

    /* async << function (text) { */   (function (text) {
                                           var _builder_$0 = Wind.builders["async"];
                                           return _builder_$0.Start(this,
                                               _builder_$0.Delay(function () {
    /*     $await(Wind.Async.sleep(1000)); */      return _builder_$0.Bind(Wind.Async.sleep(1000), function () {
    /*     console.log(text); */                       console.log(text);
    /*     return "aaa"; */                            return _builder_$0.Return("aaa");
                                                   });
                                               })
                                           );
    /* } */                            })
    //@ sourceURL=wind/0_anonymous.js
    可以看到Delay,Return等方法都是BuilderBase中的方法...
    而wind-async和wind-promise都会有一个XXXBuilder对象如PromiseBuilder..都会有Start和Bind方法,
    编译后调用的Start和Bind就是这俩个方法...
    从wind-async和wind-promise这俩个中的Start和Bind

    Start: function (_this, task) {
    return Task.create(function (t) {
    task.next(_this, function (type, value, target) {
    if (type == "normal" || type == "return") {
    t.complete("success", value);
    } else if (type == "throw") {
    t.complete("failure", value);
    } else {
    throw new Error("Unsupported type: " + type);
    }
    });
    });
    }

    这个基本一样..在type == "normal" || type == "return")是触发我们传进去的函数就哦了

    Bind也一样 按它的结构在绑定在某一时刻调用函数触发下一个任务即可..

    其实wind-async里的Start和Bind为什么要这样写都是和Task对象有关的,从这个模块的源码中就可以看到Task的定义,了解更多的用法..

    比如

    var create = Task.create = function (delegate) {
    return new Task(delegate);
    }

     Task.prototype.on = Task.prototype.addEventListener = function () {

    等等..

    下面看下fromCallback

    var fromCallback = Binding.fromCallback = function (fn) {
    var callbackArgNames = collectCallbackArgNames(arguments);

    return function () {
    var _this = this;
    var args = collectArgs(arguments, fn.length - 1);

    return Task.create(function (t) {
    args.push(function (result) {
    if (callbackArgNames) {
    var data = {};
    for (var i = 0; i < callbackArgNames.length; i++) {
    data[callbackArgNames[i]] = arguments[i];
    }

    t.complete("success", data);
    } else {
    t.complete("success", result);
    }
    });

    fn.apply(_this, args);
    });
    };
    };

    把一个异步方法变成wind方法其实很简单就包装一下返回一个task对象即可..

    可以看到它最后返回一个Task对象,当用$await或start时执行...

    它主要解决异步返回的方法..形如下面

    function ajax(str, func) {
    var n = parseInt(Math.random() * 10) * 1000;
    str += "ASYNC";
    setTimeout(function() {
    func(str);
    }, n);
    }

    var syncAjax = Wind.Async.Binding.fromCallback(ajax);

    我们在浏览器以定时器模仿一个异步...

    function ajax(str, func) {
    var n = parseInt(Math.random() * 10) * 1000;
    str += "ASYNC";
    setTimeout(function() {
    func(str);
    }, n);
    }
    var syncAjax = Wind.Async.Binding.fromCallback(ajax);

    var printAsync = eval(Wind.compile("async", function(text) {
    var a = $await(syncAjax(123));
    console.log(a);
    return a;
    }));
    console.log(printAsync().start());

    看看这个代码执行了什么

    首先启动printAsync,

    里面用await启动syncAjax(123),

    首先看看syncAjax(123)是什么,

    我们绑定syncAjax 后syncAjax就是返回的一个函数

    跟踪 var callbackArgNames = collectCallbackArgNames(arguments);,由于传的就一个函数所以callbackArgNames 为null,所以不用管,

    然后调用并传进123,

    跟踪

    var _this = this;//应该是window
    var args = collectArgs(arguments, fn.length - 1);

    args即为参数数组[123],

    $await调用syncAjax(123)执行

    args.push(function(result) {
    if (callbackArgNames) {
    var data = {};
    for (var i = 0; i < callbackArgNames.length; i++) {
    data[callbackArgNames[i]] = arguments[i];
    }

    t.complete("success", data);
    } else {
    t.complete("success", result);
    }
    });

    看到args为俩个参数[123,func]

    fn.apply(_this, args);即为

    ajax(123,func),

    所以完成时t.complete("success", result);触发...

    这时应该会调用AsyncBuilder中的Bind直接返回给结果..

    下面看一下执行的结果

    Async.Task
    1. _delegatefunction (t) {
    2. _eventManagernull
    3. _result"123ASYNC"
    4. status"succeeded"
    5. __proto__Object
    HTMLPage.htm:39
    injectScript startLiveReload init
    123ASYNC

    暂时写到这吧。

  • 相关阅读:
    重装系统之后应装软件
    中文乱码解决方案
    买电脑需要考虑的电脑配置
    JavaBean个人总结
    Servlet个人总结
    web.xml详解
    默认软件
    Eclipse导入项目
    Eclipse插件安装
    Tomcat详解
  • 原文地址:https://www.cnblogs.com/ygm125/p/2671439.html
Copyright © 2020-2023  润新知