Node.js Tutorial

Node.js在最近這幾年的人氣攀升速度非常快。你可能聽過他,卻不知道他是用來做什麼的,也不知道為什麼要使用它。此技術文件就是要來告訴大家:什麼是Node.js。

什麼是Node.js

Node.js Logo Node.js簡稱Node,近年來在網頁開發的世界中,非常火紅。很多開發人員開始將新的專案已Node.js作為開發平台。Node.js通常被使用在網頁開發。不像Apache或Nginx,他不是網頁伺服器,他比較像是PHP、Java、Ruby這樣的開發語言。那他跟這些開發語言有什麼不一樣呢。根據Node.js官方網站,答案就是:Event-drivenNon-blocking I/O mode

Event-driven

Event-driven的程式執行流程是由使用者的動作,或者是由其他程式的訊息來決定的,程式設計師會針對不同的事件,或是動作決定後續流程,而不是直接決定流程,。舉例來說,當您進入銀行,您向跟行員說明您是來存款、建立賬戶或是其他業務,行員會根據您的要求執行已經定義好的流程(SOP)。如果是非Event-driven(通常是Procedure-driven)比較像當兵,您只能依照長官的指示做完所有動作。

一般網頁或雲端APP的服務,都是Event-driven的型態,因此我們需要使用Event-driven的程式。然而,所有程式語言都可以寫出Event-driven的程式,關鍵就是在好不好寫。Node.js在設計的時候將Event-driven視為重點,因此撰寫Event-driven的程式可說是他的強項,這也是為什麼越來越多人開始使用Node.js。

Blocking Code vs Non-blocking Code

想像您今天到一間銀行進行開戶,開戶的手續大約20分鐘,其中大約有10分中的時間是您自己要填寫文件和閱讀並簽署同意書,銀行行員不需要為你做什麼事。而你的後面排了兩位要存款的客戶,存款過程大約2分鐘,如果傳統Blocking的程式語言是怎麼運作呢?它會等您做完所有事情後,再幫後面的客戶進行存款,依照順序處理。處理時間為個別任務的加總24分鐘。如下圖:

Blocking Timeline

如果是Non-blocking Code,在你填表單的過程,行員不會等你,會先幫後面的客戶做存款,直到你填好後,才會幫你繼續完成後續步驟。在這樣的流程中,節省了很多Waiting的時間,因此所需時間在20分鐘就可以做完。如下圖:

Non-blocking Timeline

除了總執行時間縮短,對後面排隊的客戶來說,等待時間更是大大減少,這也是為什麼Node.js告訴您,他很適合建立資料密集寫即時的系統。

Hello World

現在我們用一些簡單的Node.js程式與來告訴您Node.js的語法。首先當然是請您先安裝Node.js。請到Node.js官方網站下載並安裝最新的Node.js版本。

在安裝好之後,請使用您喜歡的文字編輯器,開啟一個新的檔案,並命名為helloworld.js。我們現在要在您打螢幕上打出Hello World的字樣,請輸入下面程式碼

console.log("Hello World");  

然後執行

node helloworld.js  

您就會看到Hello World顯示在您的螢幕上。

現在我們實際實作Event-driven的結果給大家看。現在我們要將Hello World打到您的網頁上。Node.js本身內建網頁相關的套件,可以直接運行類似網頁伺服器的功能。請建立一個檔案並命名為server.js,輸入以下程式碼

var http = require("http");

http.createServer(function(request, response) {  
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  console.log('someone access this page')
  response.end();
}).listen(8888);
console.log("http://localhost:8888/");  

然後執行

node server.js  

您會看到Terminal顯示"http://localhost:8888/",這個時候程式就會在背後等您,當您的瀏覽器連結此網頁時,也就是對程式做Request的時後,您應該會在瀏覽器內看到Hello World,並在您的Terminal看到someone access this page。而您每次重新整理,這行字就會印一次。這就是Event-driven的結果。當有使用者做request的時候,程式會對要求做出先對應的response,否則程式會一直等待,不會結束。

Non-blocking IO 的例子

前面我們使用了銀行的例子來告訴你什麼是Non-blocking,現在我們要直接寫程式來證明他真的是這樣運作的。請先建立一個檔案,命名為hello.txt,並輸入下列文字。

Hello World from hello.txt  

接下來請建立一個檔案命名為hello.js,並輸入下列程式

var fs = require('fs');

/** 讀取hello.txt並顯示在螢幕上 **/
fs.readFile('hello.txt', 'utf-8', function(err, data){  
  console.log(data);
});
/** 直接印出Hello World **/
console.log('Hello World from local script');  

請使用下面命令執行

node hello.js  

您會發現執行結果如下

Hello World from local script  
Hello World from hello.txt  

下面直"接印出Hello World"的程式先跑完了,才跑上面"讀取hello.txt並顯示在螢幕上",執行結果居然反了。這就是Non-blocking的厲害。傳統程式語言會按照順序做完上方程式,才會執行下面程式。但讀取檔案是很花時間的,而且電腦其實只是在等待,沒有做什麼事,所以Node.js先往下執行,在檔案讀取完成後才將讀取結果顯示出來,如同銀行行員的例子。

寫Node.js要注意的地方

我們已經示範了Node.js如何有效率的處理客戶的需求,您可能也覺得Node.js很有趣想投入心力來學習它。那您就要知道可能會犯錯的地方,因為根據本人經驗,真的很難找。

最容易犯錯的問題,就是程式執行的流程。在上面例子中,您看到了下面的程式先執行完,檔案才印出來,也就是,說如果您下面的程式是為了處理讀取出來的檔案內容,那肯定出問題的,因為他會在檔案還沒讀出來前就偷跑。如在您除錯的過程中會發現,讀取沒問題,下方程式用寫死的方式也沒問題,怎麼一起跑就是會死,那您要檢查一下是不是程式結構有問題導致執行順序不對了。

結語

感謝您看完這篇文章,如您覺得不錯,歡迎分享給需要的人,不過需要麻煩您註明出處。如有什麼需要改正的地方,或是您有任何問題,歡迎您給我們建議與指教,您可以在下方留言,或請直接來信,我們會盡力提供更多新鮮的教學文件,非常感謝您!