1. 程式人生 > >JS學習十四天----server端運行JS代碼

JS學習十四天----server端運行JS代碼

times 接口 2.6 cal dynamic 支持 benchmark target log

server端運行JS代碼

話說,當今不在client使用JS代碼才是稀罕事.因為web應用的體驗越來越豐富,client用JS實現的邏輯也越來越多,這造成的結果就是某些差點兒一致的邏輯須要在client和服務端各實現一遍,大牛們當然不甘心啊!幸運的是,我們能夠在server端運行JS代碼,誰讓JS抱了一根大腿呢...

比如,現在在client使用JS進行驗證已經是個標準,他能夠有效避免用戶在正常情況下提交錯誤的數據,增強用戶體驗.當然,server端的驗證也是不可缺少的,由於這才是安全性的體現.有些解決方式,,會在server端提供優先的驗證種類,然後在client生成JS代碼,

並輔助以server端的驗證框架.這樣的做法能夠追溯到ASP.NET上的一個控件,但這顯然會有擴展性,靈活性上的限制,因此都比較傾向與server端運行JS代碼.

比如,要檢查username是否合法,我們可能這樣寫代碼:

var checkName=function (name){return /^\w{3,10}$/.test(name);

}

這在client驗證自然沒有不論什麽問題,server端就要借助一些JavaScript運行引擎了。在.NET平臺上有比如比較新的IronJS項目,這是個基於DLRJavaScript運行引擎,十分重視性能。從作者博客上的評測結果來看。甚至率先於以速度見長的V8

可惜的是,IronJS還沒有完整實現ECMAScript 3.0。還缺少一些重要功能。比如正則表達式。

Jint是一個.NET平臺上較早的JavaScript運行引擎,因此與DLR關系不大,因此可能不太easy與IronPythonIronRuby等語言進行互操作。用它來運行一些簡單的JavaScript腳本不成問題,比如上面的代碼:

var jint = new Jint.JintEngine();jint.Run(@"var checkName = function(name) { return /^\w{3,10}$/.test(name); }");Console.WriteLine(jint.CallFunction("checkName", "jeffz")); // TrueConsole.WriteLine(jint.CallFunction("checkName", "hello world")); // False

僅僅可惜,在實際使用中,Jint不支持多線程的環境。即我們無法在多個線程下同一時候調用jintCallFunction方法,可是假設每次都又一次Run一遍JavaScript代碼,也會帶來較多的性能開銷。事實上要解決問題也並不困難,構造一個對象池就可以,.NET 4中提供了並行容器(如ConcurrentStackConcurrentQueue),實現一個簡單的對象池可謂不費吹灰之力。

這方面Jurassic的表現要好的多。這是一個構建於.NET 4.0JavaScript運行引擎:

var engine = new Jurassic.ScriptEngine();engine.Evaluate(@"var checkName = function(name) { return /^\w{3,10}$/.test(name); }");Console.WriteLine(engine.CallGlobalFunction<bool>("checkName", "jeffz"));Console.WriteLine(engine.CallGlobalFunction<bool>("checkName", "hello world"));

此外,從Benchmark上來看Jurassic性能也比Jint有所提高。但還是遠遠落後於V8。甚至IE 8裏的JavaScript引擎。並且。它還提供了一個基於Silverlight控制臺,您能夠在瀏覽器裏把玩一番。

令人感到意外的是。JintJurassic作為JavaScript執行引擎都有一些嚴重的問題,那便是不能正確執行showdown.js(JavaScript實現的Markdown轉化器)——盡管我並沒有發現showdown.js中有過於復雜的內容,基本就是些字符串操作吧。

原本我還想把它們用在mono中,既然如此也就不做進一步嘗試了。只是。經過簡單的實驗。Jurassic似乎使用了mono 2.8中尚不支持的接口,但也有可能僅僅是Jurassic控制臺中的問題。

有趣的是,.NET平臺下最靠譜的JavaScript運行引擎竟然是Rhino JavaScript,近期一次公布是在20093月,只是實現的十分完整。要說缺點,可能就是使用起來比較麻煩,還有。這是個Java項目。

嗯,我沒有開玩笑,我們全然能夠在.NET平臺下使用Rhino JavaScript

var cx = Context.enter();try{ var scope = cx.initStandardObjects(); cx.evaluateString(scope, @"var checkName = function(name) { return /^\w{3,10}$/.test(name); }", "checkName.js", 1, null); var func = (Function)scope.get("checkName", scope); Console.WriteLine(Context.toString(func.call(cx, scope, scope, "jeffz"))); Console.WriteLine(Context.toString(func.call(cx, scope, scope, "hello world"));}finally { Context.exit();}

由於我們有IKVM.NET。mono.NET開源社區上有大量寶藏。就看您能利用多少了。

我用ikvmcjs.jar轉化為RhinoJs.dll之後就能夠直接使用,效果非常好,對調試也有非常好的支持(假設JavaScript運行時出現了錯誤。則VS會直接帶您至出錯的那行)。

性能也是比較令人愜意的。在我的Mac OSX上安裝的Ubuntu Server 10.10虛擬機。單線程轉化並過濾博客上近期的3800條評論,大約耗時20秒。試驗時Host上還開著一個Windows 7虛擬機,還有大量瀏覽器等應用程序,並不十分空暇。

您可能知道,我的博客眼下是基於mono 2.6的,當中比較有特色的地方便是評論功能了。我使用Markdown標記,並提供了實時的預覽功能,這自然須要在client解釋Markdown標記,並進行過濾。

眼下。我還在server使用了C#實現的Markdown轉化器及過濾邏輯,但在某些特殊情況下結果會有所不同,且須要維護兩套代碼。不久以後。我會將把博客升級為ASP.NET 4.0mono 2.8C# 4.0dynamic特性在某些情況下的確比較方便)。而且在server端使用IKVM.NET + Rhino JavaScript運行同樣轉化代碼。從效果上來看還是十分令人愜意的。

值得一提的是,事實上在.NET平臺上另一個基於DLRJavaScript運行引擎,是為RemObjects Script for .NET,據稱也支持mono。僅僅可惜它並非開源產品(只是公開了源碼),且授權協議要求我們最多在5臺機器上安裝代碼。且僅僅供我們自己使用,於是我就沒有對它有關註太多了。

JS的第一部分完事了,本來第二部分還是想依照書上的指示下下去,發現沒啥意思.

我想這是寫點關於設計模式的東西,還是那句話,寫程序不是計算機技術,要掌握一點原理性的東西還有思想上的東西.

大三一年不準備學代碼了,學原理,學思想!

JS學習十四天----server端運行JS代碼