專門針對初學者的Node.js教程--四個例子絕對可用

瓜瓜東西發表於2014-09-04
http://www.csdn.net/article/2013-08-28/2816731-absolute-beginners-guide-to-nodejs
</pre><pre class="html" name="code">Node.js的教程並不缺乏,但有大部分教程針對已有Node.js基礎的開發者。“我已下載了Node.js,可我如何開始呢?”以下教程是專門針對Node.js初學者,文中將通過例項分享,一步步教你如何開始Node.js之旅。  

什麼是Node.js?

很多初學者並沒有真正地理解Node.js到底是什麼。nodejs.org網站中的描述也沒有多大幫助。

首先要清楚Node不是一個Web伺服器,這十分重要。它本身並不能做任何事情。它無法像Apache那樣工作。如果你希望它成為一個HTTP伺服器,你必須藉助它內建庫自己編寫。Node.js只是計算機上執行程式碼的另一種方式,它是一個簡單的JavaScript Runtime.

安裝Node.js

Node.js的安裝十分容易。只需在這裡下載滿足你需要的安裝程式即可。

已安裝好Node.js,下一步做什麼?

安裝結束後,你可以輸入一個新命令“node”。使用該“node”命令有兩種不同的方法。第一種不帶任何引數,將開啟一個互動式Shell“>”(REPL: read-eval-print-loop),你可以在這裡執行JavaScript程式碼。


[js] view plaincopyprint?
1.$ node  
2.> console.log('Hello World');  
3.Hello World  
4.undefined  
$ node
> console.log('Hello World');
Hello World
undefined



上面案例中,我在Shell中鍵入了“console.log('Hello World')”,並敲回車。Node便開始執行該程式碼,並顯示剛才記錄的資訊,同時列印出“undefined”。這是因為每條命令都會返回一個值,而console.log沒有任何返回,故輸出“undefined”。

Node命令的另一種用法是執行一個JavaScript檔案。這是我們平時最常用的方法。

hello.js


[js] view plaincopyprint?
1.<b>console.log('Hello World');</b>  
<b>console.log('Hello World');</b>[js] view plaincopyprint?
1.<b>$ node hello.js  
2.Hello World</b>  
<b>$ node hello.js
Hello World</b>



該案例中,我將“console.log('Hello World');”命令存入一個檔案中,並將該檔案作為node命令的引數。Node執行檔案中JavaScript程式碼,並輸出“Hello World”。

案例一:檔案的輸入與輸出

Node.js包含一組強大的庫(模組),可以幫助我們做很多事。第一個案例中,我將開啟一個Log檔案,並對它進行解析。

example_log.txt


[js] view plaincopyprint?
1.<b>2013-08-09T13:50:33.166Z A 2  
2.2013-08-09T13:51:33.166Z B 1  
3.2013-08-09T13:52:33.166Z C 6  
4.2013-08-09T13:53:33.166Z B 8  
5.2013-08-09T13:54:33.166Z B 5</b>  
<b>2013-08-09T13:50:33.166Z A 2
2013-08-09T13:51:33.166Z B 1
2013-08-09T13:52:33.166Z C 6
2013-08-09T13:53:33.166Z B 8
2013-08-09T13:54:33.166Z B 5</b>
該Log資料什麼意思並不重要,基本可以確定每條資訊都包含一條資料、一個字母和一個值。我希望將每個字母后面的值進行累加。

我們要做的第一件事是讀出檔案的內容。

my_parser.js


[js] view plaincopyprint?
1.<b>// Load the fs (filesystem) module   
2.var fs = require('fs');  
3.  
4.// Read the contents of the file into memory.   
5.fs.readFile('example_log.txt', function (err, logData) {  
6.  
7.  // If an error occurred, throwing it will   
8.  // display the exception and end our app.   
9.  if (err) throw err;  
10.  
11.  // logData is a Buffer, convert to string.   
12.  var text = logData.toString();  
13.});</b>  
<b>// Load the fs (filesystem) module
var fs = require('fs');

// Read the contents of the file into memory.
fs.readFile('example_log.txt', function (err, logData) {

  // If an error occurred, throwing it will
  // display the exception and end our app.
  if (err) throw err;

  // logData is a Buffer, convert to string.
  var text = logData.toString();
});</b>
通過內建的檔案(fs)模組,我們可以很容易進行檔案的輸入/輸出操作。fs模組有一個readFile方法,該方法以檔案路徑、回撥函式為引數。該回撥函式在完成檔案讀取後呼叫。檔案資料讀取後儲存在Buffer型別中,為基本的位元組陣列。我們可以通過toString()方法將它轉化為字串。

現在我們對它進行解析。

my_parser.js


[js] view plaincopyprint?
1.<b>// Load the fs (filesystem) module.   
2.var fs = require('fs');  
3.  
4.// Read the contents of the file into memory.   
5.fs.readFile('example_log.txt', function (err, logData) {  
6.  
7.  // If an error occurred, throwing it will   
8.  // display the exception and kill our app.   
9.  if (err) throw err;  
10.  
11.  // logData is a Buffer, convert to string.   
12.  var text = logData.toString();  
13.  
14.  var results = {};  
15.  
16.  // Break up the file into lines.   
17.  var lines = text.split('\n');  
18.  
19.  lines.forEach(function(line) {  
20.    var parts = line.split(' ');  
21.    var letter = parts[1];  
22.    var count = parseInt(parts[2]);  
23.  
24.    if(!results[letter]) {  
25.      results[letter] = 0;  
26.    }  
27.  
28.    results[letter] += parseInt(count);  
29.  });  
30.  
31.  console.log(results);  
32.  // { A: 2, B: 14, C: 6 }   
33.});</b>  
<b>// Load the fs (filesystem) module.
var fs = require('fs');

// Read the contents of the file into memory.
fs.readFile('example_log.txt', function (err, logData) {

  // If an error occurred, throwing it will
  // display the exception and kill our app.
  if (err) throw err;

  // logData is a Buffer, convert to string.
  var text = logData.toString();

  var results = {};

  // Break up the file into lines.
  var lines = text.split('\n');

  lines.forEach(function(line) {
    var parts = line.split(' ');
    var letter = parts[1];
    var count = parseInt(parts[2]);

    if(!results[letter]) {
      results[letter] = 0;
    }

    results[letter] += parseInt(count);
  });

  console.log(results);
  // { A: 2, B: 14, C: 6 }
});</b>
現在,當你將該檔案作為node命令的引數時,執行該命令將列印出如下結果,執行完畢後退出。


[js] view plaincopyprint?
1.$ node my_parser.js  
2.{ A: 2, B: 14, C: 6 }  
$ node my_parser.js
{ A: 2, B: 14, C: 6 }



我大部時候將Node.js作為指令碼使用,正如上面所展示的那樣。它更易於使用,是指令碼程式有力的替代者。

非同步回撥

正如在上例中看到的那樣,Node.js典型的模式是使用非同步回撥。基本上,你告訴Node.js要做的事,它執行完後便會呼叫你的函式(回撥函式)。這是因為Node是單執行緒的。在你等待回撥函式執行過程中,Node可繼續執行其他事務,不必被阻塞直到該請求完畢。

這對於Web伺服器尤其重要。在現代Web應用訪問資料庫的過程中特別普遍。當你等待資料庫返回結果的過程中,Node可以處理更多請求。與每次連線僅處理一個執行緒相比,它使你以很小的開銷來處理成千上萬個並行連線。

案例二:HTTP伺服器

Node內建有一個模組,利用它可以很容易建立基本的HTTP伺服器。請看下面案例。

my_web_server.js


[js] view plaincopyprint?
1.<b>var http = require('http');  
2.  
3.http.createServer(function (req, res) {  
4.  res.writeHead(200, {'Content-Type': 'text/plain'});  
5.  res.end('Hello World\n');  
6.}).listen(8080);  
7.  
8.console.log('Server running on port 8080.');</b>  
<b>var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8080);

console.log('Server running on port 8080.');</b>
在上面,我說是的基本HTTP伺服器。該例中所建立的並不是一個功能全面的HTTP伺服器,它並不能處理任何HTML檔案、圖片。事實上,無論你請求什麼,它都將返回“Hello World”。你執行該程式碼,並在瀏覽器中輸入“http://localhost:8080”,你將看見該文字。


[js] view plaincopyprint?
1.$ node my_web_server.js  
$ node my_web_server.js
現在你可能已經注意到一些不一樣的東西。你的Node.js應用並沒有退出。這是因為你建立了一個伺服器,你的Node.js應用將繼續執行,並響應請求,直到你關閉它。

如果你希望它成為一個全功能的Web伺服器,你必須檢查所收到的請求,讀取合適的檔案,並返回所請求的內容。值得高興的是,有人已經幫你做了這個艱難的工作。

案例三:Express框架

Express為一個框架,可使建立網站的過程十分簡單。你首先需要安裝它。除了node命令,你還需要訪問“npm”命令。利用該工具,你可以訪問社群所建立的龐大模組集。其中之一就是Express。


[js] view plaincopyprint?
1.$ cd /my/app/location  
2.$ npm install express  
$ cd /my/app/location
$ npm install express
當你安裝了一個模組,它將出現在應用程式所在目錄的“node_modules”資料夾中。現在我們可以利用Express來建立一個基本的靜態檔案伺服器。

my_static_file_server.js


[js] view plaincopyprint?
1.<b>var express = require('express'),  
2.    app = express();  
3.  
4.app.use(express.static(__dirname + '/public'));  
5.  
6.app.listen(8080);</b>  
<b>var express = require('express'),
    app = express();

app.use(express.static(__dirname + '/public'));

app.listen(8080);</b>

[js] view plaincopyprint?
1.$ node my_static_file_server.js  
$ node my_static_file_server.js
現在你已建立了一個強大的靜態檔案伺服器。你可以通過瀏覽器請求訪問你放在public資料夾中任何檔案,並進行展示,包括HTML、圖片等任何東西。比如,把一個名為“my_image.png”的圖片放在public資料夾中,你可以在瀏覽器中輸入“http://localhost:8080/my_image.png”來訪問該圖片。當然,Express還有很多特性,你可以在以後的開發中繼續探索。

NPM

上面我們已經接觸到了npm,但我仍想強調一下在Node.js開發過程中該工具的重要性。它有成千上萬個模組可幫我們解決遇到的大部分典型問題。在重新發明輪子之前,記得檢查一下npm中是否有相應功能。 

上一例中,我們手動安裝了Express。如果你的程式包含很多“依賴”(Dependency),那再利用該方法安裝它們就不合適了。為此npm提供了一個package.json檔案。

package.json


[js] view plaincopyprint?
1.<b>{  
2.  "name" : "MyStaticServer",  
3.  "version" : "0.0.1",  
4.  "dependencies" : {  
5.    "express" : "3.3.x"  
6.  }  
7.}</b>  
<b>{
  "name" : "MyStaticServer",
  "version" : "0.0.1",
  "dependencies" : {
    "express" : "3.3.x"
  }
}</b>
package.json檔案包含了應用程式的基本資訊。其中“dependencies”部分描述了你想安裝模組的名稱和版本。該案例,接受Express 3.3的任何版本。你可以在該部分列出你想要的所有依賴。

代替之前一個個安裝每個依賴,現在我們可以執行一個命令,即可將它們全部安裝完成。


[js] view plaincopyprint?
1.$ npm install  
$ npm install
執行該命令,npm將在當下資料夾中查詢“package.json”檔案。一旦找到,即可安裝所列出的所有依賴。

程式碼的組織

在大部分應用程式中,你的程式碼往往被分割到幾個檔案中。現在讓我們把最開始案例中的Log分析指令碼分離出來。這樣該程式將更易於測試與維護。

parser.js


[js] view plaincopyprint?
1.<b>// Parser constructor.   
2.var Parser = function() {  
3.  
4.};  
5.  
6.// Parses the specified text.   
7.Parser.prototype.parse = function(text) {  
8.  
9.  var results = {};  
10.  
11.  // Break up the file into lines.   
12.  var lines = text.split('\n');  
13.  
14.  lines.forEach(function(line) {  
15.    var parts = line.split(' ');  
16.    var letter = parts[1];  
17.    var count = parseInt(parts[2]);  
18.  
19.    if(!results[letter]) {  
20.      results[letter] = 0;  
21.    }  
22.  
23.    results[letter] += parseInt(count);  
24.  });  
25.  
26.  return results;  
27.};  
28.  
29.// Export the Parser constructor from this module.   
30.module.exports = Parser;</b>  
<b>// Parser constructor.
var Parser = function() {

};

// Parses the specified text.
Parser.prototype.parse = function(text) {

  var results = {};

  // Break up the file into lines.
  var lines = text.split('\n');

  lines.forEach(function(line) {
    var parts = line.split(' ');
    var letter = parts[1];
    var count = parseInt(parts[2]);

    if(!results[letter]) {
      results[letter] = 0;
    }

    results[letter] += parseInt(count);
  });

  return results;
};

// Export the Parser constructor from this module.
module.exports = Parser;</b>
在此建立了一個新檔案,來存放Log分析指令碼。這僅僅是一種標準JavaScript,還有很多方法可用來封裝該程式碼。我選擇重新定義一個JavaScript物件,這樣更容易進行單元測試。

該程式中最重要的部分是“module.exports = Parser;”這一行程式碼。它告訴Node從該檔案中要輸出的內容。在該例中,我輸出了建構函式,使用者可以用Parser物件來建立例項。你可以輸出任何你想要的。

現在我們看一下,如何匯入該檔案,來使用Parser物件。

my_parser.js


[js] view plaincopyprint?
1.<b>// Require my new parser.js file.   
2.var Parser = require('./parser');  
3.  
4.// Load the fs (filesystem) module.   
5.var fs = require('fs');  
6.  
7.// Read the contents of the file into memory.   
8.fs.readFile('example_log.txt', function (err, logData) {  
9.  
10.  // If an error occurred, throwing it will   
11.  // display the exception and kill our app.   
12.  if (err) throw err;  
13.  
14.  // logData is a Buffer, convert to string.   
15.  var text = logData.toString();  
16.  
17.  // Create an instance of the Parser object.   
18.  var parser = new Parser();  
19.  
20.  // Call the parse function.   
21.  console.log(parser.parse(text));  
22.  // { A: 2, B: 14, C: 6 }   
23.});</b>  
<b>// Require my new parser.js file.
var Parser = require('./parser');

// Load the fs (filesystem) module.
var fs = require('fs');

// Read the contents of the file into memory.
fs.readFile('example_log.txt', function (err, logData) {

  // If an error occurred, throwing it will
  // display the exception and kill our app.
  if (err) throw err;

  // logData is a Buffer, convert to string.
  var text = logData.toString();

  // Create an instance of the Parser object.
  var parser = new Parser();

  // Call the parse function.
  console.log(parser.parse(text));
  // { A: 2, B: 14, C: 6 }
});</b>
如模組一樣,檔案被引入其中,你需要輸入路徑,而非名稱。

總結

希望該教程可以幫助到你。Node.js是一個強大、靈活的技術,可以幫助解決各種各樣的問題。它已經超出了我們的想像。(編譯:陳秋歌 審校:夏夢竹)

原文連結:An absolute beginner's guide to Node.js

相關文章