久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

http://web.chinaitlab.com/web/904203.html

 quasiceo 2012-12-09
直接在瀏覽器上使用TypeScript腳本語言
中國IT實驗室收集整理  2012-10-22 12:42:23  保存本文  佚名  收藏本站

已經(jīng)有很多社區(qū)的文章在介紹 Typescript 這個新的語言,,這是理所當然的 - 因為它解決了很多JavaScript的問題,盡管處于起步階段,,卻已經(jīng)顯示了巨大的潛力,。

Typescript 要求你必須預編譯來生成 JavaScript 代碼,現(xiàn)在也可以直接在瀏覽器上動態(tài)編譯,,但你必須引用 Typescript.js 這個 JS 編譯器,,這個編譯器有 250Kb 大小,這可能是一顆很難咽下的藥丸,。

好在,,通過 ASP.NET 的瑞士軍刀 —— Web API ,我們可以實現(xiàn)對 Typescript 動態(tài)編譯為 Javascript,。

思路

為了不用再每次修改 Typescript 后都要手工編譯,,我們將透過 Web API 來為我們完成這項工作,使用的是定制的 MediaTypeFormatter.

你所需要做的就是通過一個特定的預先配置好的 Web API 路由/控制器來引用這個 JS 編譯器腳本(Typescript.js),,然后讓 Web API 管道通過 MediaTypeFormatter 來完成這項重任務,。

路由和控制器

我們在 HTML 中引用編譯后的 js 文件如下:

  1. <script type="text/javascript" src="/dynamic/scripts/demo.js"></script> 

為了實現(xiàn)這個目的,新建一個典型的 MVC4,, Web API 項目。

需要一個定制的路由和一個簡單的控制器:

  1. config.Routes.MapHttpRoute(  
  2.     name: "DynamicScripts",  
  3.     routeTemplate: "dynamic/{controller}/{name}.{ext}",  
  4.     defaults: new { name = RouteParameter.Optional, ext = RouteParameter.Optional },  
  5.     constraints: new { controller = "Scripts" }  
  6. ); 
  1. public class ScriptsController : ApiController  
  2. {  
  3.     public string Get(string name)  
  4.     {  
  5.         return name;  
  6.     }  

這個路由可以讓我們傳遞一個 name 參數(shù)和一個擴展(用于匹配所需的 filename.js),,然后控制器簡單的將文件對應的請求重定向到 formatter 中,。

插件

為了讓上述思路可行,我們需要命令行的 Typescript 編譯器,,可從 官方網(wǎng)站 上獲取,,選擇中間那個 (Plugins),推薦 Visual Studio 2012,,但 2010 也沒關系,,我們只關心命令行工具而已。

一旦安裝成功,你會找到一個名為 TCS.exe 的可執(zhí)行文件,,默認位于 C:\Program Files (x86)\Microsoft SDKs\TypeScript\0.8.0.0\. 將所有編譯器文件拷貝到解決方案目錄下的 TS 文件夾,。

格式化器/編譯器

注意下面的代碼應根據(jù)你特定的需求進行調(diào)整(包括持久化機制、錯誤處理等等):

  1. public class TypeScriptMediaTypeFormatter : MediaTypeFormatter  
  2. {  
  3.         private static readonly ObjectCache Cache = MemoryCache.Default;  
  4.  
  5.         public TypeScriptMediaTypeFormatter()  
  6.         {  
  7.             this.AddUriPathExtensionMapping("js""text/html");  
  8.         }  
  9.  
  10.         public override void SetDefaultContentHeaders(Type type, System.Net.Http.Headers.HttpContentHeaders headers, System.Net.Http.Headers.MediaTypeHeaderValue mediaType)  
  11.         {  
  12.             headers.ContentType = new MediaTypeHeaderValue("application/javascript");  
  13.         }  
  14.  
  15.         public override bool CanReadType(Type type)  
  16.         {  
  17.             return false;  
  18.         }  
  19.  
  20.         public override bool CanWriteType(Type type)  
  21.         {  
  22.             return type == typeof(string);  
  23.         }  
  24.  
  25.         public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) {  
  26.     //TODO  
  27.     }  

在我們開始寫數(shù)據(jù)到流前,,所有代碼的執(zhí)行都是很耗資源的,,注意我們設置了一些默認值,我們添加了 UriPathExtensionMapping 這樣格式化器就可以處理所有 .js 請求,。所有的輸出的內(nèi)容 content-type 將是 application/javascript ,,告訴瀏覽器這些都是 js 文件。也支持請求 text/html, 某些瀏覽器可能會這樣,。

我們只支持序列化(單向的格式化,,非反序列化),而且只接受字符串,。

WriteToStreamAsync

MediaTypeFormatter 方法根據(jù)如下流程將數(shù)據(jù)寫到流中:

1.文件名(Typescript 文件)

2.檢查 TS 文件是否存在

3.檢查緩存,,如果相應的文件已存在則使用MD5 checksum 來確保文件沒有改動

4.如果沒改動則直接從緩存中返回內(nèi)容

5.如果改動了,或者緩存文件不存在則使用 tcs.exe 編譯并返回 JS

6.將第5步生成的 JS 和 MD5 checksum 內(nèi)容保存到緩存中以便繼續(xù)使用

  1. public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)  
  2. {  
  3.    var serverPath = HttpContext.Current.Server.MapPath("~/tsc");  
  4.    var filepath = Path.Combine(serverPath, value.ToString() + ".ts");  
  5.    var jsfilepath = Path.Combine(serverPath, value.ToString() + ".js");  
  6.  
  7.    var tcs = new TaskCompletionSource<object>();  
  8.  
  9.    if (File.Exists(filepath))  
  10.    {  
  11.       string cachedItem = CheckCache(filepath, value as string);  
  12.  
  13.       if (cachedItem != null)  
  14.       {  
  15.          using (var writer = new StreamWriter(writeStream))  
  16.          {  
  17.             writer.Write(cachedItem);  
  18.          }  
  19.       }  
  20.       else 
  21.       {  
  22.          var typescriptCompiler = new ProcessStartInfo  
  23.          {  
  24.             UseShellExecute = false,  
  25.             RedirectStandardError = true,  
  26.             FileName = Path.Combine(serverPath, "tsc.exe"),  
  27.             Arguments = string.Format("\"{0}\"", filepath)  
  28.          };  
  29.  
  30.          var process = Process.Start(typescriptCompiler);  
  31.          var result = process.StandardError.ReadToEnd();  
  32.          process.WaitForExit();  
  33.  
  34.          if (string.IsNullOrEmpty(result))  
  35.          {  
  36.             using (var filestream = new FileStream(jsfilepath, FileMode.Open, FileAccess.Read))  
  37.             {  
  38.                filestream.CopyTo(writeStream);  
  39.                var fileinfo = new Dictionary<string, string>();  
  40.                fileinfo.Add("md5", ComputeMD5(filepath));  
  41.  
  42.                using (var reader = new StreamReader(filestream))  
  43.                {  
  44.                   filestream.Position = 0;  
  45.                   var filecontent = reader.ReadToEnd();  
  46.                   fileinfo.Add("content", filecontent);  
  47.                }  
  48.  
  49.                Cache.Set(value as string, fileinfo, DateTime.Now.AddDays(30));  
  50.             }  
  51.          }  
  52.          else 
  53.          {  
  54.             throw new InvalidOperationException("Compiler error: " + result);  
  55.          }  
  56.       }  
  57.    }  
  58.               
  59.    tcs.SetResult(null);  
  60.    return tcs.Task;  
  61. }  
  62.  
  63. private string CheckCache(string filepath, string filename)  
  64. {  
  65.    var md5 = ComputeMD5(filepath);  
  66.    var itemFromCache = Cache.Get(filename) as Dictionary<string, string>;  
  67.  
  68.    if (itemFromCache != null)  
  69.    {  
  70.       if (itemFromCache["md5"] == md5)  
  71.       {  
  72.          return itemFromCache["content"];  
  73.       }  
  74.    }  
  75.    return null;  
  76. }  
  77.  
  78. private string ComputeMD5(string filename)  
  79. {  
  80.    var sb = new StringBuilder();  
  81.    using (var file = new FileStream(filename, FileMode.Open, FileAccess.Read))  
  82.    {  
  83.       var md5 = new MD5CryptoServiceProvider();  
  84.       var bytes = md5.ComputeHash(file);  
  85.  
  86.       for (int i = 0; i < bytes.Length; i++)  
  87.       {  
  88.          sb.Append(bytes[i].ToString("x2"));  
  89.       }  
  90.    }  
  91.    return sb.ToString();  

這樣做的好處是文件修改時我們只需要編譯一次就可以重復使用,,這里選用的是直接在內(nèi)存中緩存,,你也可以使用其他方式,例如返回磁盤中的 js 文件之類的,。原則上,,我們是通過 MD5 checksum 來確定文件是否修改。

注意這里使用了 TCS 進程的 StandardError 屬性來判斷編譯器運行成功運行,,如果編譯過程中發(fā)生任何錯誤,,該屬性將會包含詳細的錯誤信息,否則就是空的,。

測試

假設有如下的 TS 文件,,名為 demo.ts:

  1. class Person {  
  2.    constructor(public name) { }  
  3.    sing(text) {  
  4.        return this.name + " sings " + text;  
  5.    }  

我在 HTML 頁面中引用如下,使用相同的名稱,,只是將 ts 擴展名改為 js,,這樣該請求就會觸發(fā)控制器調(diào)用編譯方法:

  1. <script type="text/javascript" src="/dynamic/scripts/demo.js"></script> 

現(xiàn)在 Web API 將即時編譯 demo.ts 并生成所需的 js 輸出到瀏覽器,而我們并沒有手工去編譯它:

而且 JS 內(nèi)容是緩存的,,以后再次刷新頁面無需重新編譯 ts 文件,。

我的調(diào)用結果:

如果修改了 Typescript 代碼:If I change the Typescript code to something else – i.e. let’s modify the sing method:

  1. class Person {  
  2. constructor ( public name ) { }  
  3. sing ( text ) {  
  4. return this . name + " sings " + text + " and it's embarassing." ;  
  5. }  

我不需要重新編譯,只需要刷新頁面,,因為 MD5 checksum 不匹配,,因此 TS 會自動重新編譯并生成新的 JS :

總結

我們前面提到的,Typescript 可使用純 JavaScript 來編譯生成 JavaScript,,但因為 JS 編譯器本身有 250Kb 大小,,因此采用了這種方法來避免編譯器的加載變得讓人無法接受,。

當然,如果你使用的是其他的 Web 開發(fā)技術,,也可以參考這個思路來實現(xiàn),。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多