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