完全面向于初學(xué)者的Node.js指南
新的上班時(shí)間是周二至周六,工作之余當(dāng)然要堅(jiān)持學(xué)習(xí)啦。
希望這篇文章能解決你這樣一個(gè)問(wèn)題:“我現(xiàn)在已經(jīng)下載好Node.Js了,該做些什么呢?”
原文URL:http://blog.modulus.io/absolute-beginners-guide-to-nodejs
本文的組成:上文的翻譯以及小部分自己的理解。所有文章中提到的JS代碼,都是經(jīng)過(guò)測(cè)試,可運(yùn)行并產(chǎn)生正確結(jié)果的。
What is Node.js?
關(guān)于Node.Js,要注意一點(diǎn):Node.js本身并不是像IIS,Apache一樣的webserver,它是一個(gè)JavaScript 的運(yùn)行環(huán)境。當(dāng)我們需要搭建一個(gè)HTTP 服務(wù)器的時(shí)候,我們可以借助Node.Js提供的庫(kù)快捷的寫(xiě)一個(gè)。
Installing Node
Node.js 安裝是非常方便的,如果你在用Windows or Mac,去這個(gè)頁(yè)面就可以了download page.
I've Installed Node, now what?
以WINDOWS為例,一旦安裝好Node.Js之后,可以通過(guò)兩種不同方式來(lái)調(diào)用Node。
方式一:CMD 下輸入node,進(jìn)入交互模式,輸入一行行的JS代碼,Node.Js會(huì)執(zhí)行并返回結(jié)果,例子:
- $ node
- > console.log('Hello World');
- Hello World
- undefined
PS:上一個(gè)例子的undefined來(lái)自于console.log的返回值。
方式二:CMD 下輸入node 文件名(當(dāng)然需要先CD到該目錄)。例子:
- hello.js 下的代碼:
- console.log('Hello World');
- $ node hello.js
- Hello World
Doing Something Useful - File I/O
使用純粹的Js原生代碼是有趣但是不利于工程開(kāi)發(fā)的,Node.JS提供了一些有用的庫(kù)(modules),下面是一個(gè)使用Node.js提供的庫(kù)分析文件的例子:
- example_log.txt
- 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
我們做的***件事情是讀出該文件的所有內(nèi)容。
- my_parser.js
- // 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();
- });
filesystem (fs 的API ref) module 提供了一個(gè)可以異步讀取文件并且結(jié)束后執(zhí)行回調(diào)的函數(shù),內(nèi)容以 Buffer的形式返回(一個(gè)byte數(shù)組),我們可以調(diào)用toString() 函數(shù),將它轉(zhuǎn)換成字符串。
現(xiàn)在我們?cè)賮?lái)添加解析部分的代碼。
- my_parser.js
- // 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 }
- });
Asynchronous Callbacks
剛才的例子中使用到了異步回調(diào),這在Node.Js編碼中是廣泛被使用的,究其原因是因?yàn)镹ode.Js是單線程的(可以通過(guò)某些特殊手段變?yōu)槎嗑€程,但一般真的不需要這么做)。故而需要各種非阻塞式的操作。
這種非阻塞式的操作有一個(gè)非常大的優(yōu)點(diǎn):比起每一個(gè)請(qǐng)求都創(chuàng)建一個(gè)線程的Web Server。Node.Js在高并發(fā)的情況下,負(fù)載是小得多的。
Doing Something Useful - HTTP Server
我們來(lái)運(yùn)行一個(gè)HTTP server吧, 直接復(fù)制 Node.js homepage.上的代碼就可以了。
- my_web_server.js
- 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.');
運(yùn)行以上代碼之后就可以訪問(wèn)http://localhost:8080 就能看到結(jié)果啦。
上面的例子顯然過(guò)于簡(jiǎn)單,如果我們需要建立一個(gè)真正的web server。我們需要能夠檢查什么正在被請(qǐng)求,渲染合適的文件,并返回。而好消息是,Express已經(jīng)做到這一點(diǎn)了。
Doing Something Useful - Express
Express 是一個(gè)可以簡(jiǎn)化開(kāi)發(fā)的框架。我們執(zhí)行npm install 來(lái)安裝這個(gè)package。
$ cd /my/app/location
$ npm install express
指令執(zhí)行完畢后,Express相關(guān)的文件會(huì)被放到應(yīng)用目錄下的node_modules文件夾中。下面是一個(gè)使用Express開(kāi)發(fā)的例子:
- my_static_file_server.js
- var express = require('express'),
- app = express();
- app.use(express.static(__dirname + '/public'));
- app.listen(8080);
- $ node my_static_file_server.js
這樣就建立了一個(gè)文件服務(wù)器。入油鍋我們?cè)?/public 文件夾放了一個(gè)"my_image.png" 。我們就可以在瀏覽器輸入http://localhost:8080/my_image.png 來(lái)獲取這個(gè)圖片. 當(dāng)然,Express 還提供了非常多的其它功能。
Code Organization
剛才的例子中我們使用的都是單個(gè)文件,而實(shí)際的開(kāi)發(fā)中,我們會(huì)設(shè)計(jì)到代碼如何組織的問(wèn)題。
我們?cè)囍鴮⒆铋_(kāi)始的文字解析程序重新組織。
- parser.js
- // 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;
關(guān)于這里的exports 的含義請(qǐng)參考我的博客:Node.Js學(xué)習(xí)01: Module System 以及一些常用Node Module.
- my_parser.js
- // 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 }
- });
這樣,文字解析的部分就被抽離了出來(lái)。
Summary
Node.js 是強(qiáng)大而靈活的。