關于服務器端JavaScript

Rhino是基于Java的JavaScript解析器,實現了通過JavaScript程序訪問整個JavaAPI,Node是Google的V8 JavaScript解析器的一個特別版本,它在底層綁定了POSIXAPI,包括文件、進程、流和套接字,并側重于異步I/O、網絡和HTTP。

用Rhino腳本化Java

Rhino是一種用java編寫的JavaScript解釋器,Rhino能自動完成JavaScript原生類型與Java原生類型之間的相互轉換。

Rhino定義的全局函數:
  • print(x); //全局輸出函數,將內容輸出到控制臺
  • version(170); //告訴Rhino需要使用JS 1.7的語言特性
  • load(filename,...); //加載并執行1個或多個JavaScript代碼文件
  • readFile(file); //讀取文本文件,并以字符串的形式返回內容
  • readUrl(url); //讀取URL的原文內容,并以字符串的形式返回內容
  • spawn(f); //運行f()或者在一個新線程中加載執行文件f
  • runCommand(cmd,[args...]); //使用O或多個命令行參數來運行系統命令
  • quit(); //退出Rhino

Rhino會將Java包和類表示成JavaScript對象,因此可以將他們賦值給變量從而得到相應的短名:

var ArrayList = java.util.ArrayList; //為類創建短名
importClass(java.util.HashMap); //其等同于:var HashMap = java.util.HashMap

Java類能使用new進行實例化,就像JavaScript類一樣:

var f = new java.io.file("/tmp/test");
var out = new java.io.FileWiter(f);

Rhino讓JavaScript的instanceof運算符能用于Java對象和類:

f instanceof java.io.file; //true
out instanceof java.io.reader //false:他是writer而非Reader
out instanceof java.io.Vloseable //true:Writer實現Closeable


  • Rhino也允許JavaScript代碼查詢、設置Java類的靜態字段和Java對象的實例字段。Java類通常利用getter和setter方法避免定義公共字段。
  • 使用for/in循環遍歷Java類和對象的方法、字段和屬性,但是不能枚舉包中的類。

Java編程經常涉及實現接口,每個事件處理程序都必須實現事件監聽接口:
實現接口.png

//用同樣的方式擴展抽象類

用同樣的方式擴展抽象類.png

//當接口只有一個方法,可以使用一個函數取而代之

用一個函數取代.png

//如果需要一個對象實現多重接口,則使用JavaAdapter

實現多重接口.png

Rhino會俺需要自動轉換為原始數字、布爾值和null。

用Node實現異步I/O

Node是基于C++的告訴JavaScript解釋器,綁定了用于進程、文件和網絡套接字底層的Unix API,還綁定了HTTP客戶端和服務器API。
由于API是異步的,因此Node依賴時間處理程序,其通常使用嵌套函數和閉包來實現 。
Node重要函數:
console.log() //調試輸出到控制臺
require()(相當于Rhino里的load()) //加載模塊,并返回其API對象


Node在process名字空間中定義了其他重要的全局屬性:

  • process.version //Node的版本字符串信息
  • process.argv //"node"命令行的數組參數,argv[0]是“node”;
  • process.env //環境變量對象 例如:process.env.PATH
  • process.pid //進程id
  • process.getuid() //返回用戶id
  • process.cwd() //返回當前的工作目錄
  • process.chdir() //改變目錄
  • process.exit() //退出(運行shutdown命令之后)

由于Node的函數和方法都是異步的,因此當他們等待運算完成時并不產生阻塞。非阻塞方法的返回值無法返回異步運算的結果。
如果想要獲取結果,就必須提供一個Node能夠調用的一個函數,在某些情況下,只需簡單的把函數作為參數傳遞,Node會適時調用它,在另外一些情況下,可以利用Node的事件機制。
Node對象產生事件,定義on()方法來注冊處理程序,當傳入參數時,將時間類型作為第一個參數,處理程序函數作為第二參數。
不同的時間類型傳遞給處理程序函數的參數不同:

  • emitter.on(nama,f) //emitter注冊f函數處理name事件
  • emitter.addListener(nama,f) //addListener()和on()是用一個方法
  • emitter.once(name,f) //只執行一次,然后f會自動刪除
  • emitter.listeners(name) //返回時間處理函數組成的數組
  • emitter.removeListener(name,f) // 注銷事件處理程序f
  • emitter.removeAllListeners(name) //移除name事件的所有處理程序
    舉例:
    //"exit"事件在Node退出之前發送
    process.on("exit",function() { console.log("Goodbye"); });

Node的設計目標是高性能I/O,因此其流API常被用到。


從文件和網絡套接字中得到流對象:
//輸入流

  • s.on("data",f); //當數據可用時,把它作為參數傳給f()
  • s.on("end",f); //當不在有數據達到,在文件結束(EOF)時會觸發"end"事件
  • s.on("error",f); //如果發生錯誤,把異常傳給f()
  • s.readable //如果他是依舊打開的可讀流,返回true
  • s.pause(); //暫停"data"時間,例如:為了限制上傳
  • s.resume(); //再次恢復

//如果想把字符串傳給"data"事件處理程序,請指定編碼

  • s.setEncoding(enc) //如何對字節編碼:"utf8"、"ascii"或"base64"

可寫流比可讀流的的核心事件少,使用write()方法發送數據,當所有數據寫入完畢后使用end()方法結束流。write方法不會阻塞,若Node方法無法立即寫入數據而不得不在內部緩存它,則write()返回false.
注冊"drain"事件的處理程序:
//輸出流

  • s.write(buffer); //寫入二進制數據
  • s.write(string,encoding) //寫入字符串數據,默認編碼是"utf-8"
  • s.end() //結束流
  • s.end(buffer); //寫入最后的二進制數據塊并結束
  • s.end(str,encoding) //寫入最后的字符串并結束所有流
  • s.writeable; //如果流依舊打開且可寫入,返回TRUE
  • s.on("drain",f) // 當內部緩沖區為空,調用f()
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容