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

 

暫時寫到這吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM