前言:寫這篇文章的由來:
1.前段時間單位有新專案啟動,服務端要做的工作不多也不算麻煩,就是處理一些中間層的服務,而且我們團隊裡面個個都會JavaScript,領導就決定試試伺服器端的JavaScript,結果本身有幸被派去研究了幾天Node,懷著雞凍的心情開始了node.js的篇章,這篇文章也就是為這幾天研究的總結。
2.一個JavaScript工程師如果沒聽過node.js那麼我想你是不是錯過了什麼,每個優秀的前端工程師都有必要去了解後台處理流程,那麼如果又能從JavaScript出發,豈不是一件很美妙的事麼。
3.互聯網的火熱使得JavaScript風光無限,且服務端的JavaScript也並不是什麼新技術了,相關的框架也有不少,只是node.js的成功讓他爆發式的出現在我們的視線中,讓很多前端工程師看到了從前端寫到後端的另一個實現希望。註:node.js 是一個允許開發人員使用 JavaScript 語言編寫伺服器端程式碼的框架。
4.今年8月曾在某大公司最後一輪(第五輪)的面試被問到Node.js的問題,相對應的回答那是相當之糟糕,結果怎樣你們懂的,感覺這個問題是導致沒有通過的關鍵點之一...那家公司是我在讀大學的時候就無比嚮往的公司,現在回想起那次經歷和過程,談不上惋惜,畢竟我真的盡力了- 其實這篇文章更多的也是為了完成自己一個小小的心結...好吧,又扯遠了。
5.歡迎各種轉載,不過請註明出處,謝謝。
Node是個啥?
寫個東西還是盡量面面俱到吧,所以有關基本概念的東西我也從網上選擇性的拿了些下來,有些地方針對自己的理解有所改動,對這些概念性的東西有過了解的可選擇跳過這段。
1.Node 是一個伺服器端JavaScript 解譯器,可是真的以為JavaScript不錯的同學學習Node就能輕鬆拿下,那麼你就錯了,總結:水深不深我還不知道,不過確實不淺。
2.Node 的目標是幫助程式設計師建立高度可伸縮的應用程序,編寫能夠處理數萬條同時連接到一個實體機的連接程式碼。處理高並發和非同步I/O是Node受到開發人員的關注的原因之一。
3.Node 本身運行Google V8 JavaScript引擎,所以速度和效能非常好,看chrome就知道,而且Node對其封裝的同時也改進了其處理二進位資料的能力。因此,Node不僅簡單的使用了V8,還對其進行了最佳化,使其在各種環境下更加給力。 (什麼是V8 JavaScript 引擎?請「百度知道」)
4.第三方的擴充和模組在Node的使用中扮演重要的角色。下面也會介紹下載npm,npm就是模組的管理工具,用它安裝各種 Node 的軟體包(如express,redis等)並發布自己為Node寫的軟體包 。
安裝Node
在這簡單說說在window7和linux兩種環境下安裝Node。安裝的時候一定要注意Python的版本,多次因為Python版本的問題安裝失敗,建議2.6 的版本,低版本會出現Node安裝錯誤,查詢Python版本可在終端機中輸入:pyhton -v
1.先介紹linux下的安裝吧,Node在Linux環境下的安裝和使用都非常方便,建議在Linux下運行Node,^_^...我使用的是Ubuntu11.04
a.安裝依賴套件:50-100kb/s大概每個包一分鐘就能下載安裝完成
sudo apt-get install g++ curl libssl-dev apache2-utils sudo apt-get install git-core
b.在終端一步一步執行一下指令:
git clone git://github.com/joyent/node.git cd node ./configure make sudo make install
安装顺利的话到这一步Node就算安装成功了,2M的网络用了共计12分钟。
注:如果不用git下载也可以直接下载源码,不过这样下载安装需要注意Node版本问题。使用git下载安装是最方便的,所以推荐之。
2.在Windows下使用Cygwin安装Node,这个方式不太推荐,因为真的需要较长时间和较好的人品。我的系统是 win7旗舰版
Cygwin是一个在windows平台上运行的unix模拟环境,下载地址:http://cygwin.com/setup.exe。
下载好Cygwin后开始安装,步骤:
a.选择下载的来源 - Install from Internet
b.选择下载安装的根目录
c.选择下载文件所存放的目录
d.选择连接的方式
e.选择下载的网站 - http://mirrors.163.com/cygwin
f.麻烦就麻烦在这步,考验人品的时候到了。需要的下载安装时间不确定,反正需要比较长的时间(超过20分钟),偶尔会出现安装失败的情况。单击一下各个程序包前面的旋转箭头图标选择你想要的版本,选中时会出现了"x"号表示已经选中了该程序包。选择需要下载的程序包:
Devel包:
gcc-g++: C++ compiler
gcc-mingw-g++: Mingw32 support headers and libraries for GCC C++
gcc4-g++: G++ subpackage
git: Fast Version Control System – core files
make: The GNU version of the ‘make' utility
openssl-devel: The OpenSSL development environment
pkg-config: A utility used to retrieve information about installed libraries
zlib-devel: The zlib compression/decompression library (development)
Editor包:vim: Vi IMproved – enhanced vi editor
Python包:把Default切换成install状态即可
Web包:
wget: Utility to retrieve files from the WWW via HTTP and FTP
curl: Multi-protocol file transfer command-line tool
上个截图,以下载zlib-devel为例:
其上几步走完才算把环境搭建完成,可是现在还没有到安装Node,还需要在Cywgin的ASH模式下执行rebaseall,步骤如下:
a. cmd命令行
b. 进入cygwin安装目录下的bin子目录
c. 运行ash进入shell模式
d. ./rebaseall -v
e. 没有错误就关闭命令行窗口
好了,现在到下载安装Node了,启动Cygwin.exe后输入:
$ wget http://nodejs.org/dist/node-v0.4.12.tar.gz
$ tar xf node-v0.4.12.tar.gz
$ cd node-v0.4.12
$ ./configure
$ make
$ make install
3.直接下载node.exe文件
nodejs.org下载较慢所以我在网盘上传了一个,下载地址:http://www.everbox.com/f/VhyL6EiGF5Lm3ZSRx85caFDIA5
听说有不太稳定的问题,不过你假如只是想先在windows下了解Node,个人感觉这个方法比你装个Cygwin好很多。
注:原本不太想写安装Node这段,可是为了这篇文章的全面性还是写了,没想到一写就是那么长一段了...茶几了
“Hello World” - 为什么每次见到这句心情都会小激动,不解...
首先,创建个hello.js的文件,在文件中copy如下代码:
var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(1337, "127.0.0.1"); console.log('Server running at http://127.0.0.1:1337/');
代码逻辑:
a. 全局方法require()是用来导入模块的,一般直接把 require() 方法的返回值赋值给一个变量,在 JavaScript 代码中直接使用此变量即可 。require("http") 就是加载系统预置的 http 模块
b. http.createServer 是模块的方法,目的就是创建并返回一个新的web server对象,并且给服务绑定一个回调,用以处理请求。
c. 通过 http.listen() 方法就可以让该 HTTP 服务器在特定端口监听。
d. console.log就不用多说了,了解firebug的都应该知道,Node实现了这个方法。
注: 想了解具体细节请查看文档 cnodejs.org/cman/all.html#http.createServer
接着运行Node服务器,执行hello.js代码,成功启动会看见console.log()中的文本。有图有真相:
npm的下载和使用
除Node本身提供的API外,现在有不少第三方模块可极大的提高开发效率,npm就是Node的软件包管理器,可以用它安装所需软件包并发布自己为nodejs写的软件包。官网地址:npmjs.org
安装只需要在终端写入一行代码:
npm安装node扩展包同样是一行代码:
//例:npm install express
注:如果安装模块的过程中报域名错误的话,请清空缓存 >npm cache clean 或重启计算机即可。
理解Node的模块概念
在Node中,不同的功能组件被划分成不同的模块。应用可以根据自己的需要来选择使用合适的模块。每个模块都会暴露一些公共的方法或属性。模块的使用者直接使用这些方法或属性即可,对于内部的实现细节就可以不用了解。除了Node本身提供的API外,开发人员也可以利用这个机制来将应用拆分成多个模块,以提高代码的可复用性。
1.如何使用模块?
在Node中使用模块是非常方便的,在 JavaScript 代码中可以直接使用全局函数 require() 来加载一个模块。
在刚刚”Hello World"的例子中,require("http") 可以加载系统预置的 http 模块;模块名称以 "./" 开始的,如 require("./myModule.js") 用来加载与当前 JavaScript 文件同一目录下的 myModule.js 模块。
2.自己如何开发模块?
刚刚介绍使用require()导入模块的时候,模块名称以 "./" 开始的这种,就是自己开发的模块文件。需要注意的就是JS文件的系统路径。
代码中封装了模块的内部处理逻辑,一个模块一般都会暴露一些公开的方法或属性给其他的人使用。模块的内部代码需要把这些方法或属性给暴露出来。
3.来一套简单的例子。先创建一个模块文件如myModule.js,就一行代码
console.log('Hi Darren.')
然后创建一个test.js文件,导入这个JS文件,执行node看到结果
现在Node社区中已有不少第三方的模块,希望能有更多人通过学习Node,加入到这个大家庭中,为Node社区来添砖加瓦。先谢谢之,咱们继续。
4.来一个深点的例子。这个例子中将会针对 私有和共有 进行介绍。先创建一个myModule.js,代码如下:
var name = "Darren"; this.location = "Beijing"; this.showLog = function(){ console.log('Hi Darren.') };
代码中出现了三种类型,分别是: 私用属性,共有属性和共有方法,再创建一个test.js,执行Node
结果高亮的地方很清楚的告诉我们,私有方法我们在模块以外是取不到的,所以是undefined。共有属性和共有方法的声明需要在前面加上 this 关键字。
Node能做什么和它的优势
Node核心思想: 1.非阻塞; 2.单线程; 3.事件驱动。
在目前的web应用中,客户端和服务器端之间有些交互可以认为是基于事件的,那么AJAX就是页面及时响应的关键。每次发送一个请求时(不管请求的数据多么小),都会在网络里走一个来回。服务器必须针对这个请求作出响应,通常是开辟一个新的进程。那么越多用户访问这个页面,所发起的请求个数就会越来越多,就会出现内存溢出、逻辑交错带来的冲突、网络瘫痪、系统崩溃这些问题。
Node的目标是提供一种构建可伸缩的网络应用的方案,在hello world例子中,服务器可以同时处理很多客户端连接。
Node和操作系统有一种约定,如果创建了新的链接,操作系统就将通知Node,然后进入休眠。如果有人创建了新的链接,那么它(Node)执行一个回调,每一个链接只占用了非常小的(内存)堆栈开销。
举一个简单的异步调用的例子,把test.js和myMydule.js准备好了,^_^。把以下代码拷贝到test.js中并执行:
var fs = require('fs'); fs.readFile('./myModule.js', function (err, data) { if (err) throw err; console.log('successfully'); }); console.log('async');
所谓的异步,大家应该都能想得到运行时会先打先显示"async",再显示"successfully"。
Node是无阻塞的,新请求到达服务器时,不需要为这个请求单独作什么事情。Node仅仅是在那里等待请求的发生,有请求就处理请求。
Node更擅长处理体积小的请求以及基于事件的I/O。
Node不仅仅是做一个Web服务的框架,它可以做更多,比如它可以做Socket服务,可以做比方说基于文件的,然后基于像一些比方说可以有子进程,然后内部的,它是一个很完整的事件机制,包括一些异步非注射的解决方案,而不仅仅局限在网络一层。同时它可能,即使作为一个Web服务来说,它也提供了更多可以深入这个服务内核、核心的一些功能,比方说Node使用的Http Agent,这块就是它可以更深入这个服务内核来去做一些功能。
Node事件流概念
因为Node 采用的是事件驱动的模式,其中的很多模块都会产生各种不同的事件,可由模块来添加事件处理方法,所有能够产生事件的对象都是事件模块中的 EventEmitter 类的实例。代码是全世界通用的语言,所以我们还是用代码说话:
var events = require("events"); var emitter = new events.EventEmitter(); emitter.on("myEvent", function(msg) { console.log(msg); }); emitter.emit("myEvent", "Hello World.");
简单的分析这段:
1. 使用require()方法添加了events模块并把返回值赋给了一个变量
2. new events.EventEmitter()这句创建了一个事件触发器,也就是所谓的事件模块中的 EventEmitter 类的实例
3. on(event, listener)用来为某个事件 event 添加事件处理方法监听器
4. emit(event, [arg1], [arg2], [...]) 方法用来产生事件。以提供的参数作为监听器函数的参数,顺序执行监听器列表中的每个监听器函数。
EventEmitter 类中的方法都与事件的产生和处理相关:
1. addListener(event, listener) 和 on(event, listener) 这两个方法都是将一个监听器添加到指定事件的监听器数组的末尾
2. once(event, listener) 这个方法为事件为添加一次性的监听器。该监听器在事件第一次触发时执行,过后将被移除
3. removeListener(event, listener) 该方法用来将监听器从指定事件的监听器数组中移除出去
4. emit(event, [arg1], [arg2], [...]) 刚刚提到过了。
在Node中,存在各式各样不同的数据流,Stream(流)是一个由不同对象实现的抽象接口。例如请求HTTP服务器的request是一个流,类似于stdout(标准输出);包括文件系统、HTTP 请求和响应、以及 TCP/UDP 连接等。流可以是可读的,可写的,或者既可读又可写。所有流都是EventEmitter的实例,因此可以产生各种不同的事件。
可读流主要会产生以下事件:
data 当读取到流中的数据时,此事件被触发
end 当流中没有数据可读时,此事件被触发
error 当读取数据出现错误时,此事件被触发
close 当流被关闭时,,此事件被触发,可是并不是所有流都会触发这个事件。(例如,一个连接进入的HTTP request流就不会触发'close'事件。)
还有一种比较特殊的 fd 事件,当在流中接收到一个文件描述符时触发此事件。只有UNIX流支持这个功能,其他类型的流均不会触发此事件。
相关详细文档:http://cnodejs.org/cman/all.html#events_
强大的File System 文件系统模块
Node 中的 fs 模块用来对本地文件系统进行操作。文件的I/O是由标准POSIX函数封装而成。需要使用require('fs')访问这个模块。所有的方法都提供了异步和同步两种方式。
fs 模块中提供的方法可以用来执行基本的文件操作,包括读、写、重命名、创建和删除目录以及获取文件元数据等。每个操作文件的方法都有同步和异步两个版本。
异步操作的版本都会使用一个回调方法作为最后一个参数。当操作完成的时候,该回调方法会被调用。而回调方法的第一个参数总是保留为操作时可能出现的异常。如果操作正确成功,则第一个参数的值是 null 或 undefined 。
同步操作的版本的方法名称则是在对应的异步方法之后加上一个 Sync 作为后缀。比如异步的 rename() 方法的同步版本是 renameSync() 。下面列出来了 fs 模块中的一些常用方法,都只介绍异步操作的版本。
test.js和myModule.js文件准备好了木?把下面这段代码copy到test.js中执行一次
var fs = require('fs'); fs.unlink('./myModule.js', function (err) { if (err) throw err; console.log('successfully deleted myModule.js'); });
如果沒有報error,那麼myModule.js就被刪除了,就是這麼簡單
這只是一個簡單的例子,感興趣的話自己去多多嘗試,實踐出真理。由於篇幅原因就不多舉例了。 ^_^
學習Node的總結:
1.對於一個linux的命令和shell知識幾乎為零的我來說,這段時間又學到了不少關於linux知識;vim真是一個強大的編輯器,不用滑鼠的感覺真的很好;而且有一點對我來說很重要,在linux下編程很cool,尤其是在團隊中都是使用windows的,裝裝更健康^_^。
2.了解服務端JavaScript的一個成功框架-Node,以及它的一些優點和使用的方式,這篇文章就是最好的總結,當然,這只會是一個開始。
3.對於沒有進入那麼夢想的公司其實是有那麼點遺憾,不過生活就應該要這樣,有波折有起伏,這正是我需要並且期待的...那麼新的生活還是要繼續,做自己的舵手,把握好自己的方向,過去的就讓它過去吧。
一些想對大夥說的話:
1. 在這我得打擊一部分人的積極性。假如你對後台技術不夠了解或沒接觸過服務端語言,不知道I/O這些知識,沒有後台處理流程這種概念,那麼......Node並不是一門適合入門的服務端技術。為什麼這麼說:
a.重點就是中文實例少,文章少,想系統的學習會比較麻煩,所以在使用過程中總有一種不成熟的感覺,當然主要還是因為我對它不熟悉所造成的。國內使用Node的公司確實不多,當然國外還是有不少了,從cnodejs.org截了一個圖:
b.對沒有經驗的朋友來說node其實並不好上手,從最簡單「Hello world」就可以看出來(各種運行環境和安裝細節的了解都得費點功夫),不要以jQuery庫為比較,所處理的事物不同,學習的成本也不同- 所以不太建議作為新手入門的服務端技術,如果想學習一門服務端語言PHP和Python都是不錯的選擇,因為:書多例子多框架多上手簡單容易理解搭建方便...
c.以上都是我個人善意的建議,由於水平有限,請大家多多指教,希望嘴下留情。
2. 關於Node的書寫規範和具體技巧本人就不獻醜了,自己寫Node的程式碼也不多,不過物件導向的程式設計思想在哪都是好使的。
以上內容是小編跟大家介紹的nodejs初步體驗篇,希望大家喜歡。