精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用node.js進行服務器端JavaScript編程

開發 前端
node.js 是一個可以使用 JavaScript 開發服務器端應用的平臺。它依托于 Google V8 JavaScript 引擎,并采用事件 I/O 的架構,可以用來創建高性能服務器。本文詳細介紹了 node.js 的基本知識、模塊化的結構、事件驅動的機制以及常用的模塊。

隨著 Web 2.0 概念和 Ajax 技術的流行,JavaScript 作為 Ajax 應用開發中必不可少的一部分,已經得到了廣泛的流行。開發人員也開始逐步的熟悉和掌握 JavaScript,并積累了相關的開發經驗。雖然 JavaScript 目前主要用在 Web 應用中,以瀏覽器作為運行平臺,但是已經有相關的嘗試把 JavaScript 遷移到服務器端,這其中包括 Aptana 的 Jaxer 等。這種做法與 Google GWT 是異曲同工的。Google GWT 允許開發人員使用 Java 語言來編寫 Web 前端代碼。這兩種做法的目的都是為了復用開發人員已經掌握的知識和積累的經驗。在這點上,node.js 類似于 Jaxer。

簡單的來說,node.js 是一個允許開發人員使用 JavaScript 語言編寫服務器端代碼的框架。也就是說編寫的 JavaScript 代碼可以直接運行在本地機器上,而不僅限于瀏覽器。從實現的角度來說,Jaxer 和 node.js 都使用了已有的 JavaScript 執行引擎。Jaxer 用的是 Mozilla Firefox 中使用的 JavaScript 引擎,而 node.js 用的則是 Google Chrome 中用的 V8 引擎。

node.js 入門

node.js 可以運行在 Linux、Windows 和 Macintosh 等主流的操作系統上。在 Windows 平臺上運行 node.js 的話,需要 Cygwin 或是 MinGW 的支持。下面以常用的 Windows 平臺為例來說明。首先需要安裝 Cygwin。安裝的時候需要選擇 gcc-g++ 、make、openssl 和 python 等包。gcc 的版本必須是***的。接著從 參考資料 中給出的地址下載 node.js 0.4.0 版本的源代碼。下載解壓之后,依次在 Cygwin 中運行 ./configure 、make 和 make install 等命令進行編譯和安裝。安裝完成之后,直接運行 node 命令就可以啟動 node.js 提供的命令行。在命令行中可以直接輸入 JavaScript 代碼并運行。也可以通過 node server.js 的方式來運行一個 JavaScript 文件 server.js 。

代碼清單 1 中給出了一個簡單的“Hello World”程序的示例。通過 node helloworld.js 來運行該 JavaScript 文件之后,會在控制臺輸出“Hello World”。

清單 1. 使用 node.js 的“Hello World”程序

  1. process.stdout.write("Hello World"); 

代碼清單 1 中的 process 表示的是當前運行的 node.js 進程,其屬性 stdout 表示的是進程的標準輸出流。通過 write() 方法向給流中寫入一個字符串。從 代碼清單 1 可以看到,使用 JavaScript 就可以訪問標準輸出流等本地系統上的資源。這從一個側面反映出來了 node.js 的強大。

在 node.js 可以運行的 JavaScript 代碼中,可以使用一些全局的對象:包括 代碼清單 1 中用到的 process 、下面會介紹的用來加載模塊的 require() 方法、表示當前正在執行的 JavaScript 文件名的 __filename 、表示當前正在執行的 JavaScript 文件的目錄的__dirname 和與瀏覽器中相似的用來執行定時任務的 setTimeout() 和 setInterval() 方法等。

在介紹了 node.js 的基本知識之后,下面介紹 node.js 的模塊化結構。

模塊化結構

node.js 使用了 CommonJS 定義的模塊系統。不同的功能組件被劃分成不同的模塊。應用可以根據自己的需要來選擇使用合適的模塊。每個模塊都會暴露一些公共的方法或屬性。模塊使用者直接使用這些方法或屬性即可,不需要關系模塊內部的實現細節。除了系統預置的多個模塊之外,應用開發團隊也可以利用這個機制來將應用拆分成多個模塊,以提高代碼的可復用性。

使用模塊

在 node.js 中使用一個模塊的方式是非常簡單的。使用某個模塊之前需要首先聲明對它的依賴。在 JavaScript 代碼中可以直接使用全局函數 require() 來加載一個模塊。如 require("http") 可以加載系統預置的 http 模塊。而 require("./myModule.js") 用來加載與當前 JavaScript 文件同一目錄下的 myModule.js 模塊。如果使用 require() 的路徑以“/”開頭的話,則認為是模塊 JavaScript 文件在操作系統上的絕對路徑。如果不是這兩種情況的話,node.js 就會嘗試在當前 JavaScript 文件的父目錄及其祖先目錄下的 node_modules目錄下查找。比如目錄 /usr/home/my.js 中調用了 require("other.js") 的話,node.js 會依次嘗試查找下列文件:/usr/home/node_modules/other.js 、/usr/node_modules/other.js 和 /node_modules/other.js 。

require() 方法的返回值是該模塊所暴露出來的公開 JavaScript 對象,包含了可供使用的方法和屬性。代碼清單 2 給出了模塊的基本使用方式。

清單 2. 模塊的基本使用方式

  1. var greetings = require("./greetings.js");   
  2. var msg = greetings.sayHello("Alex", "zh_CN");   
  3. process.stdout.write(msg); 

如 代碼清單 2 所示,一般是直接把 require() 方法的返回值賦值給一個變量,在 JavaScript 代碼中直接使用此變量即可。greetings.js 模塊暴露了一個 sayHello() 方法,當前 JavaScript 代碼直接使用了該方法。

開發自己的模塊

開發自己的模塊的基本工作是在模塊對應的 JavaScript 文件中編寫模塊相關的代碼。這其中封裝了模塊的內部處理邏輯。一般來說,一個模塊通常會暴露一些公開的方法或屬性給其使用者。模塊的內部代碼需要把這些方法或屬性給暴露出來。代碼清單 3 給出了 代碼清單 2 中所使用的 greetings.js 文件的內容。

清單 3. greetings.js 模塊的內容

  1. var languages = {   
  2.     "zh_CN" : "你好,",   
  3.     "en" : "Hello, "  
  4.  };        
  5.  exports.sayHello = function(name, language) {   
  6.     return languages[language] || languages["en"] + name;   
  7.  }; 

如 代碼清單 3 所示,exports 對象的內容就是模塊的使用者調用 require() 方法的返回值中所包含的內容。模塊通過這種方式來聲明其所暴露出來的公開方法和屬性。在模塊中定義的變量,如 languages ,是只對模塊內部的代碼可見的。

如果一個模塊所包含的內容比較多,也可以用文件夾的方式來組織。可以在文件夾的根目錄下面創建一個 package.json 文件,其內容中包含了模塊的名稱和入口 JavaScript 文件的路徑。如果沒有提供這個 package.json 文件的話,node.js 會默認在文件夾中查找index.js 文件作為模塊的啟動 JavaScript 文件。

在介紹完 node.js 的模塊化結構之后,下面介紹其事件驅動機制。

事件驅動

開發過 Web 應用的人都熟悉瀏覽器中的事件處理機制。當對某個 DOM 元素上的某類事件感興趣的時候,只需要在該 DOM 元素上面注冊一個事件監聽器即可。如 ele.addEventListener("click", function() {}) 就添加了一個對 click 事件的監聽器。當事件發生的時候,事件監聽器的 JavaScript 方法就會被調用。事件的處理方法是異步執行的。這種異步執行的方式非常適合于開發高性能并發網絡應用。實際上,目前的高性能并發應用開發一般有兩種做法:***種是使用多線程的機制,另外一種就是采用基于事件驅動的方式。多線程的問題在于應用開發起來難度較高,很容易出現線程饑餓或是死鎖等問題,對開發人員提出了更高的要求。而事件驅動的方式則更加靈活,很容易為 Web 開發人員所理解和使用,也不存在線程死鎖等問題。依托于性能強大的 Google V8 引擎和先進的事件 I/O 架構,node.js 可以成為創建高性能服務器端應用的良好基礎。

基于 node.js 開發應用與開發 Web 應用有相似的編程模型。很多模塊都會暴露出一些事件,使用這些模塊的代碼通過注冊事件監聽器的方式來添加相應的處理邏輯。代碼清單 4 中給出了一個簡單的 HTTP 代理服務器的實現代碼。

清單 4. HTTP 代理服務器

  1. var http = require("http");   
  2. var url = require("url");   
  3.  
  4. http.createServer(function (req, res) {   
  5.    var urlObj = url.parse(req.url, true); // 獲取被代理的 URL   
  6.    var urlToProxy = urlObj.query.url;   
  7.    if (!urlToProxy) {   
  8.        res.statusCode = 400;   
  9.        res.end("URL 是必須的。");   
  10.    }   
  11.    else {   
  12.        console.log("處理代理請求:" + urlToProxy);   
  13.        var parsedUrl = url.parse(urlToProxy);   
  14.        var opt = {   
  15.            host : parsedUrl.hostname,   
  16.            port : parsedUrl.port || 80,   
  17.            path : (parsedUrl.pathname || "") + (parsedUrl.search || "")   
  18.                + (parsedUrl.hash || "")   
  19.        };   
  20.        http.get(opt, function(pres) { // 請求被代理 URL 的內容  
  21.            res.statusCode = pres.statusCode;   
  22.            var headers = pres.headers;   
  23.            for (var key in headers) {   
  24.                res.setHeader(key, headers[key]);   
  25.            }   
  26.            pres.on("data"function(chunk) {   
  27.                res.write(chunk); // 寫回數據  
  28.            });   
  29.            pres.on("end"function() {   
  30.                res.end();   
  31.            });   
  32.        });   
  33.    }   
  34. }).listen(8088, "127.0.0.1");   
  35.  
  36. console.log("代理服務器已經在 8088 端口啟動。"); 

整個代理服務器的實現比較簡單。首先通過 http 模塊中的 createServer() 方法用來創建一個 HTTP 服務器,再通過 listen() 方法就可以讓該 HTTP 服務器在特定端口監聽。在 createServer() 方法中傳入的參數是 HTTP 請求的響應方法。實際上,每個 HTTP 請求都是對應于 HTTP 服務器上的一個 request 事件。代碼清單 4 中的 HTTP 服務器創建部分實際上等價于 代碼清單 5 中給出的實現方式。

清單 5. 使用事件機制的 HTTP 服務器創建方式

  1. var server = http.createServer();   
  2. server.on("request"function(req, res) {   
  3. }); 

在請求的處理方法里面,通過 http.get() 方法來獲取被代理 URL 的內容。這里同樣采用了基于事件的處理方式。pres.on("data", function(chunk) {}) 在 pres 的 data 事件上添加了一個處理方法。該方法的作用是當獲取到被代理 URL 的內容的時候,就把獲取到的內容寫回到原始 HTTP 請求的響應中。對于 end 事件的處理也是同樣的。在使用 node.js 進行開發的時候,會經常遇到這種使用事件處理方法和回調方法的場景。

在介紹了 node.js 的事件驅動機制之后,下面介紹一些常用的模塊。

#p#

常用模塊

node.js 默認提供了很多與網絡與文件系統操作相關的模塊。這些模塊是構建服務器端應用的基礎。下面對其中一些常見的模塊進行具體說明。

事件模塊

前面提到過,node.js 采用的是事件驅動的架構,其中的很多模塊都會產生各種不同的事件,可以由模塊使用者來添加事件處理方法。所有能夠產生事件的對象都是事件模塊中的 EventEmitter 類的實例。

EventEmitter 類中的方法都與事件的產生和處理相關,如下所示:

◆ addListener(event, listener) 和 on(event, listener) :這兩個方法的作用都是用來為某個事件 event 添加事件處理方法listener 。

◆ once(event, listener) :這個方法為某個事件 event 添加僅執行一次的處理方法 listener 。處理方法在執行一次之后就會被刪除。

◆ removeListener(event, listener) :該方法用來刪除某個事件 event 上的處理方法 listener 。

◆ emit(event, [arg1], [arg2], [...]) :該方法用來產生某個事件 event 。事件名稱 event 之后的參數被傳遞給對應的事件處理方法。

代碼清單 6 給出了事件模塊的使用示例。

清單 6. 事件模塊的使用示例

  1. var events = require("events");   
  2.  var emitter = new events.EventEmitter();   
  3.  emitter.on("myEvent"function(msg) {   
  4.     console.log(msg);   
  5.  });   
  6.  emitter.emit("myEvent""Hello World."); 

在事件模塊中有一個特殊的事件 error 。當出現錯誤的時候,EventEmitter 會產生此事件。如果此事件沒有對應的處理方法的話,默認的行為是輸出錯誤信息后,程序自動終止。因此,需要注意總是添加一個對 error 事件的處理方法。

node.js 中存在各式各樣不同的數據流,包括文件系統、HTTP 請求和響應、以及 TCP/UDP 連接等。這些流都是 EventEmitter 的實例,因此可以產生各種不同的事件。流可以分成只讀、只寫和讀寫流三種。

可讀流主要會產生 4 個事件:

◆ data :當讀取到流中的數據時,產生此事件。

◆ end :當流中沒有數據可讀時,產生此事件。

◆ error :當讀取數據出現錯誤時,產生此事件。

◆ close :當流被關閉時,產生此事件。

除了上面的事件之外,還有一個 pipe() 方法可以用來把當前的可讀流和另外一個可寫流連接起來。可讀流中的數據會被自動寫入到可寫流中。

可寫流中最常用的是 write() 和 end() 兩個方法。write() 方法用來向流中寫入數據,而 end() 則用來結束寫入操作。

為了表示二進制數據,node.js 使用了類 Buffer 來表示數據緩沖區,以對二進制數據進行操作。Buffer 類內部是以數組的方式來存儲數據的。一旦創建出來之后,Buffer 的大小是不能被修改的。Buffer 類的實例是可以與 JavaScript 中的字符串類型互相轉換的。在轉換的時候需要指定編碼格式。通過 Buffer 類的 toString(encoding, start, end) 方法可以把 Buffer 中的從 start 到 end 的內容轉換成以 encoding 編碼的字符串。可以支持的編碼格式有:ascii 、utf8 和 base64 。通過 new Buffer(str, encoding) 可以用一個字符串 str 來初始化一個緩沖區。write(string, offset, encoding) 用來把一個字符串 string 以編碼格式 encoding 寫入到緩沖區中以 offset 開始的位置上。

網絡操作

node.js 提供了一些與網絡操作相關的模塊,包括 TCP、UDP 和 HTTP 等,可以實現網絡服務器和客戶端。

與 TCP 協議相關的實現在 net 模塊中。通過該模塊的 createServer(connectionListener) 方法可以創建一個 TCP 服務器。參數connectionListener 是當有客戶端連接到該服務器上時的處理方法,等價于對 connect 事件的處理。一個 TCP 服務器是類 Server 的實例。通過 listen 方法可以讓服務器在指定端口監聽。

如果想連接到一個已有的 TCP 服務器的話,可以使用 createConnection(port, host) 方法來連接到指定主機 host 的端口 port 上。該方法的返回值是 Socket 類的實例,表示一個套接字連接。得到一個 Socket 類的實例之后,就可以通過 write() 方法來向該連接中寫入數據。如果想從該連接上獲取數據的話,可以添加 data 事件的處理方法。

代碼清單 7 中給出了一個簡單的用來進行表達式計算的 TCP 服務器,可以通過 telnet 命令連接到此服務器來進行測試。

清單 7. 簡單的表達式計算服務器

  1. var net = require("net");   
  2.  var server = net.createServer(function(socket) {   
  3.     socket.setEncoding("utf8");   
  4.     var buffer = [], len = 0;   
  5.     socket.on("data"function(data) { // 接收到客戶端數據  
  6.         if (data.charCodeAt(0) == 13) {   
  7.             var expr = buffer.join("");   
  8.             try {   
  9.                 var result = eval(expr); // 進行計算  
  10.                 socket.write(result.toString()); // 寫回結果  
  11.             } catch (e) {   
  12.                 socket.write("Wrong expression.");   
  13.             } finally {   
  14.                 socket.write("\r\n");   
  15.                 buffer = [];   
  16.             }   
  17.         }   
  18.         else {   
  19.             buffer.push(data);   
  20.         }   
  21.     });   
  22.  });   
  23.  server.listen(8180, "127.0.0.1");   
  24.  console.log("服務器已經在端口 8180 啟動。"); 

除了 TCP 服務器外,模塊 http 和 https 可以分別實現 HTTP 和 HTTPS 服務器,模塊 dgram 可以實現 UDP/Datagram 套接字連接,模塊 tls 可以實現安全的套接字連接(SSL)。這些模塊的使用方式都類似于模塊 tcp 。

文件系統

node.js 中的 fs 模塊用來對本地文件系統進行操作。fs 模塊中提供的方法可以用來執行基本的文件操作,包括讀、寫、重命名、創建和刪除目錄以及獲取文件元數據等。每個操作文件的方法都有同步和異步兩個版本。異步操作的版本都會使用一個回調方法作為***一個參數。當操作完成的時候,該回調方法會被調用。而回調方法的***個參數總是保留為操作時可能出現的異常。如果操作正確成功,則***個參數的值是 null 或 undefined 。而同步操作的版本的方法名稱則是在對應的異步方法之后加上一個 Sync 作為后綴。比如異步的 rename() 方法的同步版本是 renameSync() 。下面列出來了 fs 模塊中的一些常用方法,都只介紹異步操作的版本。

◆ rename(path1, path2) :將路徑 path1 表示的目錄或文件重命名成路徑 path2 。

◆ truncate(fd, len) :將文件描述符 fd 對應的文件的長度截斷為 len 。

◆ chmod(path, mode) :將路徑 path 表示的目錄或文件的權限修改為 mode 。

◆ stat(path) :獲取路徑 path 表示的目錄或文件的元數據。元數據用 Stats 類來表示。

◆ open(path, flags, mode) :打開一個路徑 path 表示的文件。回調方法中可以得到該文件的描述符。

◆ read(fd, buffer, offset, length, position) :讀取給定文件描述符 fd 所表示的文件中從 position 位置開始的長度為length 字節的數據,并存放到緩沖區 buffer 中從 offset 起始的位置上。回調方法中可以得到實際讀取的字節數。

◆ write(fd, buffer, offset, length, position) :將緩沖區 buffer 中的數據寫入到文件描述符 fd 所表示的文件中。參數的含義與 read() 方法一樣。回調方法中可以得到實際寫入的字節數。

◆ readFile(filename, encoding) :以編碼格式 encoding 來讀取一個文件 filename 中的內容。回調方法中可以得到文件的內容。

◆ writeFile(filename, data, encoding) :將數據 data 以編碼格式 encoding 寫入到文件 filename 中。

除了上面列出來的直接操作文件本身的方法外,還可以把文件轉換成流。createReadStream(path, options) 和createWriteStream(path, options) 分別用來從文件中創建可讀和可寫流。參數 path 表示的是文件的路徑,options 是一個表示讀取或寫入文件時的選項的 JavaScript 對象。

代碼清單 8 中給出了一個簡單的 HTTP 靜態文件服務器的實現。

清單 8. HTTP 靜態文件服務器

  1. var http = require("http"),   
  2.     fs = require("fs"),   
  3.     path = require("path"),   
  4.     url = require("url");   
  5.  
  6.  var server = http.createServer(function(req, res) {   
  7.     var pathname = url.parse(req.url).pathname;   
  8.     var filepath = path.join("/tmp""wwwroot", pathname);   
  9.     var stream = fs.createReadStream(filepath, {flags : "r", encoding : null});   
  10.     stream.on("error"function() {   
  11.         res.writeHead(404);   
  12.         res.end();   
  13.     });   
  14.     stream.pipe(res);   
  15.  });   
  16.  server.on("error"function(error) {   
  17.     console.log(error);   
  18.  });   
  19.  server.listen(8088, "127.0.0.1"); 

如代碼清單 8 所示,首先把 HTTP 請求的路徑轉換成服務器上文件路徑,再從文件中創建可讀流,***通過 pipe() 方法把文件的數據流傳遞到 HTTP 請求的響應中。

#p#

輔助模塊

除了上面介紹的這些常見模塊之外,node.js 還提供了一些輔助的模塊。

模塊 path 用來處理文件系統上的路徑。這個模塊中的 join() 用來把多個路徑連接起來,形成一個完整的路徑。如 join("/usr", "home", "test/index.html") 的結果是路徑 /usr/home/test/index.html 。normalize() 用來對路徑進行歸一化操作,去掉其中多余的“/”以及處理“..”和“.”。resolve([from ...], to) 方法用來獲取給定路徑 to 的絕對路徑。如果 to 不是絕對路徑,就把它之前的參數按從右到左的順序添加上去,直到得到了一個絕對路徑。如果到***還是無法得到絕對路徑,就把當前的工作目錄加上。假設當前的工作目錄是 /usr/home ,那么 resolve("test", "index.html") 的返回結果是 /usr/home/test/index.html 。dirname() 方法用來獲取路徑的目錄部分。如 dirname("/usr/home/index.html") 的返回結果是 /usr/home 。basename() 用來獲取路徑的***一個部分。如basename("/usr/home/index.html") 的返回結果是 index.html 。extname() 用來獲取一個路徑的文件擴展名部分。如extname("/usr/home/index.html") 的返回結果是 .html 。

模塊 url 用來對 URL 進行解析。parse(urlStr, parseQueryString) 方法用來把一個 URL 字符串 urlStr 解析成主機名、端口和路徑等幾個部分。該方法的返回值是一個包含了 protocol 、hostname 、port 、pathname 和 query 等屬性的 JavaScript 對象。如果參數 parseQueryString 的值為 true 的話,URL 中包含的查詢字符串部分也會被解析。format(urlObj) 方法的作用與 parse() 方法正好相反,用來從一個 JavaScript 對象中構建出 URL 字符串。

模塊 querystring 用來處理 URL 中的查詢字符串。stringify(obj) 方法用來把一個 JavaScript 對象 obj 轉換成查詢字符串的格式。如 stringify({a : 1, b : "good"}) 的返回結果是 a=1&b=good 。parse(str) 用來把一個查詢字符串解析成 JavaScript 對象。

模塊 vm 可以用來執行 JavaScript 代碼。方法 runInThisContext(code) 用來執行一段 JavaScript 代碼 code 并返回其結果。通過該方法運行的 JavaScript 代碼不能訪問當前代碼的作用域。runInNewContext(code, [sandbox]) 方法也是用來執行 JavaScript 代碼的,與 runInThisContext() 不同的是通過該方法運行的 JavaScript 代碼使用 sandbox 對象作為全局對象。如 runInNewContext("a + 3", {a : 4}) 的返回結果是 7。createScript(code) 方法用來預先編譯一段 JavaScript 代碼,但是并不立即執行。該方法的返回值是一個 Script 對象。該對象同樣有 runInThisContext() 和 runInNewContext([sandbox]) 兩個方法,含義與上面提到的兩個方法類似。

模塊 os 提供了與底層操作系統相關的一些信息。包括 hostname() 用來獲取操作系統的主機名;type() 用來獲取操作系統的類型;release() 用來獲取操作系統的發行版本號;uptime() 用來獲取以秒計算的系統運行時間;cpus() 用來獲取 CPU 的相關信息。freemem() 和 totalmem() 分別用來獲取系統的內存總數和可用內存數。

模塊 util 提供了一些常用的輔助方法。debug(string) 方法用來輸出信息到標準錯誤流。log(string) 方法用來輸出附帶時間戳的信息到標準輸出流。inspect(object, showHidden, depth) 方法用來輸出一個對象的內部結構,參數 object 是要查看的對象,showHidden 表示是否查看對象的隱藏屬性,depth 表示查看的對象層次結構的深度,默認值是 2。inherits(constructor, superConstructor) 方法用來實現 JavaScript 中基于原型的繼承機制。

在介紹完 node.js 提供的常用模塊之后,下面通過一個完整的示例來說明 node.js 的用法。

實例分析

這個實例實現的功能是動態監測服務器的內存使用狀態,即內存的占用率。獲取服務器上的內存占用率比較簡單,只需要使用 os 模塊提供的方法即可,即 freemem()/totalmem() 。為了能夠實時的監測內存占有率,服務器需要實時的把數據傳輸給瀏覽器端。這里***的實現方式是 HTML 5 中引入的 WebSocket 規范。該規范在 Firefox 4 和 Google Chrome 等新瀏覽器上得到了支持。同時服務器端也需要支持此規范。Socket.IO 在 node.js 上提供了對 WebSocket 規范的支持,包括服務器端和瀏覽器端代碼。代碼清單 9 給出了使用 Socket.IO 的服務器端代碼。

清單 9. 監測內存占用率的服務器端代碼

  1. var io = require('./socket.io');   
  2.  var io = io.listen(server);   
  3.  io.on("connection"function(client){   
  4.     setInterval(function() {   
  5.         client.send(os.freemem() / os.totalmem());   
  6.     }, 500);   
  7.  }); 

在 代碼清單 9 中,server 是 node.js 中的一個 HTTP 服務器對象,用來響應一般的 HTTP 請求。Socket.IO 可以對 node.js 的 HTTP 服務器的請求進行攔截,將部分請求交給 Socket.IO 來處理。這里的處理邏輯是當有客戶端連接上的時候,就每隔 500 毫秒把服務器的內存占用率發送給客戶端。代碼清單 10 給出了瀏覽器端的 HTML 和 JavaScript 代碼。

清單 10. 監測內存占用率的瀏覽器端代碼

  1. <!doctype html>   
  2.  <html>   
  3.   <head>   
  4.     <title> 服務器內存使用情況 </title>   
  5.     <script src="/socket.io/socket.io.js"></script>   
  6.     <style>   
  7.         #usage {border : 1px dashed green;}   
  8.     </style>   
  9.     <script>   
  10.         var canvas, width = 200, height = 200, buffer = [], max = 200;   
  11.         function updateChart(data) {   
  12.             if (buffer.length >= max) {   
  13.                 buffer.unshift();   
  14.             }   
  15.             buffer.push(data);   
  16.             var ctx = canvas.getContext("2d");   
  17.             ctx.clearRect(0, 0, width, height);   
  18.             for (var i = 1, n = buffer.length; i < n; i++) {   
  19.                 ctx.strokeStyle = "red";   
  20.                 ctx.beginPath();   
  21.                 ctx.moveTo(i - 1 , buffer[i - 1] * height);   
  22.                 ctx.lineTo(i, buffer[i] * height);   
  23.                 ctx.closePath();   
  24.                 ctx.stroke();   
  25.             }   
  26.         }   
  27.       
  28.         function onLoad() {   
  29.             canvas = document.getElementById("usage");   
  30.             var socket = new io.Socket(null, {port: 8088});   
  31.             socket.connect(); // 連接到服務器  
  32.             socket.on("message"function(obj){ // 接收到消息時的處理方法  
  33.                 updateChart(obj);   
  34.             });   
  35.         }   
  36.     </script>   
  37.   </head>   
  38.   <body onload="onLoad();">   
  39.     <h1> 內存使用情況 </h1>     
  40.     <canvas id="usage" width="200" height="200"></canvas>   
  41.   </body>   
  42.  </html> 

 

 

 

 

 

 

 

 

 

 

如 代碼清單 10 所示,首先建立一個與服務器之間的 WebSocket 連接。通過 message 事件定義了當接收到服務器端的消息時,更新瀏覽器端的顯示。瀏覽器端通過一個 HTML 5 提供的 canvas 來繪制內存占用率的曲線圖,如 圖 1 所示。

圖 1. 內存占用率的曲線圖

 

內存占用率的曲線圖

 

總結

一提到服務器端開發,開發人員一般想到的就是Java 和 C/C++ 等語言。但是通過 node.js 提供的強大能力,熟悉 JavaScript 的 Web 開發人員也可以開發出服務器端的應用。本文詳細介紹了 node.js 的事件驅動機制和模塊化結構,并對其中的常用模塊做了詳細說明,***通過一個完整的實例展示了 node.js 的實用性。

原文:http://www.ibm.com/developerworks/cn/web/1107_chengfu_nodejs/index.html

【編輯推薦】

  1. 淺析Node.js:一個“編碼就緒”服務器
  2. Node.js 0.4.8發布 附下載
  3. JavaScript入門
  4. JavaScript內核之基本概念
  5. JavaScript與生俱來的10個設計缺陷
責任編輯:陳貽新 來源: developerWorks
相關推薦

2011-09-08 10:21:50

Node.js

2021-09-02 10:49:25

Node.jsPHP服務器開發

2021-05-26 09:00:00

Node.js開發模塊

2020-10-12 08:06:28

HTTP 服務器證書

2013-12-25 11:01:16

JavaScript

2012-10-15 13:40:15

IBMdw

2019-02-15 10:49:37

Node.jsweb服務器

2018-04-22 00:01:43

JavaScript Node 語言

2010-10-15 08:57:15

PHP多進程

2016-08-25 21:28:04

前端node截圖

2024-07-08 08:53:52

2016-08-04 13:44:20

CentOS6.xNodejs解決方案

2010-03-23 10:04:00

JavaScript

2022-08-28 16:30:34

Node.jsDocker指令

2019-01-22 15:28:04

Javascriptvue.jsnuxt.js

2020-10-29 16:00:03

Node.jsweb前端

2021-09-16 10:31:08

服務器編程 語言PHP

2009-02-16 16:30:23

OperaTurbo服務器

2018-12-06 11:30:42

JavaScript前端編程語言

2021-06-15 15:03:21

MongoDBNode.jsCRUD
點贊
收藏

51CTO技術棧公眾號

亚洲小视频在线播放| 欧美激情精品久久久久久大尺度| 国产a视频免费观看| 伦理片一区二区三区| 久久精品国产成人一区二区三区| 久久成人国产精品| 国产在线观看无码免费视频| 国产69精品久久久久按摩| 一二三区精品视频| 日本精品一区| 亚洲欧美黄色片| 美女性感视频久久| 3344国产精品免费看| 开心激情五月网| 亚洲免费观看高清完整版在线观| 欧美精品久久99久久在免费线| 成人免费在线网| 91福利在线视频| 99免费精品视频| 91亚洲精品久久久| 国产成人无码专区| 亚洲性感美女99在线| 色妞久久福利网| 日本黄色动态图| 精品伊人久久| 欧美日韩视频在线第一区 | 精品白丝av| 日韩天堂在线视频| 中文字幕在线看高清电影| 成人短视频软件网站大全app| 欧美三级欧美成人高清www| 国产激情片在线观看| 尤物网在线观看| 久久久亚洲精品一区二区三区| 超碰97国产在线| 国产精品高潮呻吟AV无码| 老司机精品视频网站| 97在线精品视频| 久久久综合久久久| 午夜国产一区| 久久亚洲电影天堂| 中文字幕资源站| 郴州新闻综合频道在线直播| 亚洲欧美日韩区| www.久久国产| 妖精一区二区三区精品视频| 精品亚洲一区二区三区| 国产精品麻豆入口| 加勒比久久高清| 精品久久久久久久人人人人传媒 | 一本久道高清无码视频| 尤物yw193can在线观看| 亚洲日本护士毛茸茸| 综合网五月天| free性欧美hd另类精品| 亚洲人精品午夜| 特大黑人娇小亚洲女mp4| 超碰在线最新| ...中文天堂在线一区| 成人在线视频电影| 亚洲精品成av人片天堂无码| 国产91综合网| 久久99欧美| 男男激情在线| 国产精品美日韩| 福利网在线观看| 日韩三级电影视频| 午夜精品久久久久久久99樱桃| 欧美精品一区免费| 国产v综合v| 欧美日韩综合在线| 图片区乱熟图片区亚洲| 盗摄牛牛av影视一区二区| 亚洲国产三级网| 国产sm调教视频| 国产精品7m凸凹视频分类| 欧美xxxx做受欧美.88| 欧美成人手机视频| 亚洲综合三区| 国产日韩欧美91| 亚洲av色香蕉一区二区三区| 成人91在线观看| 欧美日韩精品一区| 激情在线小视频| 黄色一区二区三区| 日韩一级免费片| www.成人网| 亚洲欧美日韩另类| 久久久精品视频免费观看| 亚洲国产三级| 国产精品久久久久免费a∨大胸| 一区二区日韩在线观看| 成人福利视频网站| 亚洲一区3d动漫同人无遮挡 | 一本一道久久a久久精品蜜桃| 欧美美女操人视频| 中文字幕69页| 国产风韵犹存在线视精品| 玖玖玖精品中文字幕| 免费看美女视频在线网站| 亚洲福中文字幕伊人影院| 成人黄色一区二区| 国产成人精品福利| 精品国内自产拍在线观看| 青青草av在线播放| 国产在线国偷精品免费看| 久久涩涩网站| 亚洲91av| 欧美精品在线观看播放| 少妇特黄一区二区三区| 在线国产一区二区| 国产精品美女免费视频| 天天干视频在线观看| 日韩毛片高清在线播放| 精品久久久久久久免费人妻| 91蝌蚪精品视频| 精品国产自在精品国产浪潮| 夜夜爽妓女8888视频免费观看| 粉嫩久久99精品久久久久久夜| 亚洲一区二区精品在线| 在线天堂新版最新版在线8| 日韩欧美在线不卡| 九九热久久免费视频| 亚洲一区二区动漫| 国产精品区一区二区三在线播放 | 欧美最猛性xxxx| 亚洲精品97久久中文字幕| 亚洲欧洲日韩在线| 手机在线免费观看毛片| 久久av影视| 5252色成人免费视频| 亚洲伦理在线观看| 亚洲永久免费视频| 亚洲 自拍 另类 欧美 丝袜| 99久久夜色精品国产亚洲1000部| 国产成人精品综合久久久| 同心难改在线观看| 亚欧色一区w666天堂| www.四虎在线| 一区三区视频| 精品国产二区在线| 国产精品25p| 亚洲精品国偷自产在线99热| 69精品久久久| 成人黄色小视频在线观看| 日本精品久久久久久久久久| 麻豆国产精品| 欧美巨乳在线观看| 亚洲av无码国产精品久久不卡 | 欧美成年网站| 超碰精品一区二区三区乱码| 国产视频一区二区三| 亚洲女人****多毛耸耸8| 精品人妻一区二区三| 欧美涩涩网站| 国产一区国产精品| 天堂中文在线播放| 亚洲一二三在线| 中文字幕一区二区人妻视频| 国产午夜精品一区二区三区视频 | 日韩精品一区二区三| av在线这里只有精品| 成熟了的熟妇毛茸茸| 国产欧美高清视频在线| 国产精品自产拍在线观| 二区三区在线观看| 精品三级在线观看| 九一国产在线观看| 欧美激情综合在线| 在线视频日韩欧美| 在线国产精品一区| 日韩资源av在线| www一区二区三区| 欧美韩国理论所午夜片917电影| 欧美 日韩 国产 成人 在线 91| 婷婷六月综合网| 免费网站在线高清观看| 精品亚洲成a人| 日本中文字幕亚洲| 欧美在线免费看视频| 亚洲精品日产aⅴ| 免费看男女www网站入口在线| 亚洲色图综合网| 国产美女永久免费| 欧美视频中文在线看| 黄色一级片一级片| 成人激情黄色小说| 天天操,天天操| 影院欧美亚洲| 少妇特黄a一区二区三区| 精品国产第一国产综合精品| 性欧美激情精品| 在线免费观看黄色| 亚洲精品久久久久中文字幕二区 | 亚洲欧洲自拍| 久久国产精品久久国产精品| 午夜在线视频免费| 欧美久久一区二区| 国产精品黄色网| 成人欧美一区二区三区| 好吊一区二区三区视频| 激情综合网av| 成年人视频在线免费| 欧美日韩三级| 伊人久久av导航| 美女亚洲一区| 国产另类自拍| 成人在线视频国产| 国产精品 欧美在线| 女同视频在线观看| 精品国内自产拍在线观看| 免费人成在线观看网站| 精品国产欧美一区二区| 136福利视频导航| 91九色02白丝porn| 久久午夜免费视频| 亚洲综合一区二区三区| 久久精品日韩无码| 国产免费观看久久| 欧美熟妇精品黑人巨大一二三区| 国产91在线|亚洲| 午夜免费福利网站| 另类调教123区| 看欧美ab黄色大片视频免费| 国产精品久久久一区二区| 日韩精品综合在线| 欧美va亚洲va日韩∨a综合色| 先锋影音日韩| 精品freesex老太交| 久久精品国产理论片免费| av成人综合| 成人av电影免费| 色悠久久久久综合先锋影音下载| 国产日韩欧美黄色| 91精品国产一区二区在线观看 | 久久悠悠精品综合网| 99精品国产一区二区| 国产成年精品| 亚洲bt欧美bt日本bt| 国产午夜精品一区在线观看| 国产在线观看91精品一区| 色婷婷成人网| 成人性教育视频在线观看| 四虎地址8848精品| 成人性生交大片免费看小说| 日韩城人网站| 91啪国产在线| 日韩精品视频一区二区三区| 91精品国产99久久久久久红楼| 欧美高清hd| 超碰在线观看97| 久久97久久97精品免视看秋霞| 国产精品一区二区在线观看| 粉嫩精品导航导航| 精品国产一区二区三区免费| 欧美激情影院| 欧洲成人一区二区| 999精品在线| 国产精品8888| 国产日韩欧美一区二区三区在线观看| 日韩欧美视频网站| 日韩在线观看一区二区| 国产一二三区av| 国产麻豆精品95视频| 日韩黄色一区二区| 97国产精品videossex| 国产真实乱人偷精品人妻| 国产精品久久久久精k8 | 精品动漫av| 四虎永久在线精品无码视频| 青椒成人免费视频| 一级黄色高清视频| av中文字幕亚洲| 妖精视频在线观看免费| 亚洲激情一二三区| 男人午夜免费视频| 欧美人xxxx| 国产成人无码www免费视频播放| 日韩高清a**址| 欧美成人精品一区二区男人看| 久久99热精品| 欧美freesex| 亚洲综合在线小说| 国产麻豆精品久久| 欧美日韩视频免费| 久久婷婷一区| 91av免费观看| 国产亚洲一区二区在线观看| 久久久精品视频免费观看| 欧美日韩在线免费观看| 91在线精品入口| 日韩激情在线视频| 操你啦在线视频| 日本中文字幕久久看| 九色精品蝌蚪| 青青草国产精品| 影音先锋亚洲一区| 中文字幕免费高清在线| 91污片在线观看| 我家有个日本女人| 欧美特级限制片免费在线观看| 亚洲男女视频在线观看| www.日韩av.com| 韩国成人动漫| 国产精品国产精品| 999精品在线| 国产野外作爱视频播放| 不卡电影免费在线播放一区| 男女男精品视频网站| 欧美日韩国产在线播放| 精品人妻伦一区二区三区久久| 国产一区二区av| 蜜桃视频动漫在线播放| 成人午夜影院在线观看| 91精品啪在线观看国产81旧版| 欧美极品欧美精品欧美图片| 成人精品小蝌蚪| 九九久久免费视频| 在线不卡中文字幕| 国产在线视频网| 欧洲永久精品大片ww免费漫画| 三级欧美日韩| 永久免费看av| 国产在线看一区| 极品美妇后花庭翘臀娇吟小说| 色国产综合视频| 秋霞av在线| 欧美在线视频播放| 美女主播精品视频一二三四| 欧美黄色免费网址| 国产精品一区二区免费不卡 | 亚洲成av人片在线观看无码| 99热这里只有精品1| 精品久久国产精品| 亚洲精品第一| 一区二区三区日韩视频| 青青草视频一区| 91l九色lporny| 欧美影院一区二区| 国产69久久| 国产精品爽黄69天堂a| 久久神马影院| 亚洲激情在线看| 亚洲欧洲无码一区二区三区| 怡红院成永久免费人全部视频| 一本久久综合亚洲鲁鲁| 日韩欧美一区二区三区免费观看 | 中文字幕在线播放视频| 午夜精品福利一区二区蜜股av| 少妇高潮久久久| 亲爱的老师9免费观看全集电视剧| 久久99精品国产自在现线| 免费高清在线观看免费| 久久久国际精品| 伊人亚洲综合网| 久久夜色精品国产欧美乱| 欧美日韩黄网站| 九色自拍视频在线观看| 91视频www| 欧美高清69hd| 久热99视频在线观看| 亚洲一二av| 国产精品宾馆在线精品酒店| 国产香蕉久久精品综合网| 一级片免费观看视频| 免费成人高清视频| 欧美日韩一区二区三区不卡视频| 国产亚洲精品网站| 国产精品国产三级国产aⅴ中文 | 亚洲精品久久久久久下一站 | 97超级碰碰人国产在线观看| 九色丨蝌蚪丨成人| 日韩 欧美 高清| 中文字幕中文字幕一区二区| 99热这里只有精品66| 2021国产精品视频| 欧美成人自拍| 亚洲av永久无码精品| 色婷婷亚洲精品| 成人黄色网址| 麻豆蜜桃91| 精品一区二区三区香蕉蜜桃 | av在线free| 久久精品女人的天堂av| 奇米影视一区二区三区| 久久午夜无码鲁丝片| 亚洲欧美国产视频| 国产精品日本一区二区不卡视频| 视频一区二区综合| 大白屁股一区二区视频| 国产在线观看第一页| 欧美日本高清视频| 精品视频日韩| 亚洲午夜久久久久久久久| 欧美亚日韩国产aⅴ精品中极品| 色女人在线视频| 亚洲精品高清国产一线久久| 福利一区二区在线| 在线视频你懂得| 91精品国产乱码久久久久久久久 |