對於Nodejs,相信客官並不陌生,網上卻已衆說紛紜,有人說是一個平臺,有人說是服務器JavaScript,有人說一個框架…html
以前亦有過研究,多懷可遠觀而不可褻玩也。高效率,I/O操做,異步編程,以及高併發處理!!java
因而乎,懷着這份忐忑與景仰yu好奇,以前有自學過一段時間,這些日子公司項目完測,遂整理了一些Nodejs學習筆記,這裏純屬分享下本身的筆記(說不定之後還能奉承寶典咧,想一想都有點雞凍)也有從別處借鑑過來的知識,如有雷同,不勝榮幸,供客官參考,若有不足多多指教node
推薦讀書 樸靈《深刻淺出nodeJs》web
ok,不廢話,手記攤開npm
「旨在提供一種簡單的構建可伸縮網絡程序的方法」編程
這是Nodejs官方的宣言json
哈哈哈,這逼裝的我要給103分,不解釋windows
Node.js是啥?數組
Nodejs 不是一種獨立的語言瀏覽器
Nodejs 是一個讓JavaScript運行在服務端的開發的平臺
服務器端的JavaScript
容許開發人員使用JavaScript語言寫服務器端代碼的框架(其實Nodejs是對Commonjs規範的一種很好的實現)
其自己利用Google V8 JavaScript引擎,因此速度和性能很是好,並且Nodejs又對其進行了封裝,同時還改進了其處理二進制數據的能力(Nodejs對引入過的模塊都會進行緩存,且核心模塊的緩存檢查先於文件模塊的緩存檢查)
Nodejs不是一個web服務器,只是計算機上執行代碼的另外一種方式,它是一個簡單的JavaScript Runtime.
js是由客戶端而產生,Nodejs爲網絡而生
Node能作什麼?
具備複雜邏輯的網站
局域社交網站的大web的應用
Web Scoket服務器
TCP/UDP套接字應用程序
命令行工具
交互式終端程序
這有啥拽的,從技術上說就是各類的封裝,並無新大陸呀??!!!!我大微軟C#也能解決,給你個.Net本身體會去吧,後面跟着C/C++,路過…
說到這點,這兒有一位,絕壁的狠狠的噴了一把, SolidMango 《NODE.JS之我見》
總之,各執其詞,很差定論,正如SolidMango所說,堅守己見,不要盲從,看本身怎麼理解吧。
Node的優勢:
1. 它是一個JavaScript運行環境 (Nodejs採用C++語言編寫而成)
2. 依賴於瀏覽器V8引擎進行代碼解釋
3. 事件驅動
4. 非阻塞
5. 異步I/O
6. 輕量、可伸縮,適於實時數據交互應用
7. 單進程,單線程
Node.Js最大特性是採用異步式I/O與事件驅動的架構設計。對於高併發的解決方案,傳統的架構是多線程模型,也就是每一個業務邏輯提供一個系統線程,經過系統線程切換來彌補同步式I/O調用時的時間開銷.
Node.Js採用的是單線程模型,在執行過程當中會維護一個事件隊列,程序在執行時在進入事件循環等待下一個事件的到來。
累了,困了,來個小demo緩解一下----
ps 我學習是在windows上開發,固然*nix會更好
Nodejs安裝。。。。此處略去n千字…
驗證是否安裝成功:運行cmd,輸入 node –v
順帶着把版本(v6.2.0)也檢查了一下,哈哈哈… 好好雞賊了一把
我用Visual Studio Code開發Nodejs,固然也有蠻多不錯的的IDE:webstorm,notepad++ ,sublime,Eclipse等等
一、新建hello.js,裏面寫入
console.log(' Hello World ');
保存格式utf-8。存放在d:\NodeJs\demo\hello.js
二、運行cmd命令
cmd ——》 D: ——》cd nodejs ——》cd demo ——》node hello.js
還有另一種方式
1. 運行cmd,輸入node,回車 進入Nodejs的編譯模式
Console.log(‘Hello World’);
2. 輸出結果:
第一行是結果
第二行是返回值
ok,再來提高一下逼格
Nodejs較牛逼地方,就是對Http的封裝 (Nodejs其底層已是封裝好的服務器)
建立hello.js文件,裏面寫入
var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World'); }).listen(1337, "127.0.0.1"); console.log('Server is running at http://127.0.0.1:1337/');
代碼分析:
a. 全局方法require()是用來導入模塊的,通常直接把 require() 方法的返回值賦值給一個變量,可直接使用此變量。require("http") 就是加載系統預置的 http 模塊
b. http.createServer 是模塊的方法,目的就是建立並返回一個新的web server對象,而且給服務綁定一個回調,用以處理請求。
c. 經過 http.listen() 方法就可讓該 HTTP 服務器在特定端口監聽。
瀏覽器運行結果以下:
當一個request到來時,EventLoop會將這個Listener回調函數放入執行隊列, Nodejs中全部的代碼都是一個一個從執行隊列中拿出來執行的。
這些執行都是在工做線程上(Event Loop自己能夠認爲在一個獨立的線程中,咱們通常不提這個線程,而將Nodejs稱呼爲一個單線程的執行環境),
全部的回調都是在一個工做線程上運行。
EventLoop 指的是計算機系統的一種運行機制。簡單的說就是,在程序中設置兩個線程:一個是負責程序自己的運行,稱爲「主線程」;另外一個負責主線程與其餘進程(主要是I/O操做)的通訊。 也能夠叫 「消息線程」
開發Nodejs程序,調試的時候,不管修改了那一部分代碼,都須要重啓服務才能生效,這是由於Nodejs只有在第一次引用到某部分的時候纔會去解析腳本,之後都會直接訪問內存,避免重複載入
缺點:提升了效率,卻不利於程序調試
解決方案:supervisor ,會監視對代碼的改動,並自動重啓Node.js
安裝supervisor:用npm安裝,輸入命令符 npm -g install supervisor
ps:必須安裝到全局,不然錯誤命令也會提示安裝到全局
or:修改全局路徑到當前路徑 npm config set prefix "路徑"
supervisor server.js //開始監視server.js
可是若是出錯,會不停的刷cmd,以及網頁間斷性報錯
Node.Js的異步式IO與事件式編程
Node.js最大的特性就是異步式I/O與事件緊密結合的編程模式。這種模式與傳統的同步式IO線性的編程思路有很大的不一樣,由於控制流很大程度上要靠事件和回調函數來組織,一個邏輯要拆分爲若干個單元格。
內容:阻塞和線程
1. 同步式I/O或阻塞式I/O
線程在執行中若是遇到磁盤讀寫或網絡通訊,一般要耗費較長時間。這時操做系統會剝奪這個線程的CPU控制權,使其暫停執行,同時將資源讓給其餘的工做線程,這種線程調度方式成爲阻塞,當I/O操做完畢時,操做系統將這個線程的阻塞狀態解除,恢復其對CPU的控制權、令其繼續執行。
2. 異步式I/O或非阻塞式I/O
針對全部I/O操做不採用阻塞策略,當線程遇到I/O操做時,不會以阻塞的方式等待I/O操做的完成或數據的返回,而只是將I/O請求發送給操做系統,繼續執行下一條語句,當操做系統完成I/O操做時,以事件的形式通知執行I/O操做的線程,線程會在特定時候處理這個事件,爲了處理異步I/O,線程必須有事件循環,不斷的檢查有沒有未處理的事件,依次予以處理。
3. 非阻塞與阻塞模式區別
非阻塞模式下,一個線程永遠在執行計算操做,這個線程所使用的CPU核心利用率永遠是100%,IO以事件的方式通知。
阻塞模式下,多線程每每能提升系統吞吐量,由於一個線程阻塞還有其餘線程在工做,多線程可讓CPU資源不被阻塞中的線程浪費。
調度:當前一個工做,在5分鐘以後執行
4. 同步式IO與異步式IO區別
同步式IO(阻塞式) |
異步式IO(非阻塞) |
利用多線程提供吞吐量 |
單線程便可實現高吞吐量 |
經過事件片分割和線程調度利用多核CPU |
經過功能劃分利用多核 |
須要由操做系統調度多線程使用多核CPU |
能夠將單線程綁定到單核CPU |
難以充分利用CPU資源 |
能夠充分利用CPU資源 |
內存軌跡大,數據局部性弱 |
內存軌跡小,數據局部性強 |
符合線性的編程思惟 |
不符合傳統編程思惟 |
異步式 少了多線程的開銷 不符合傳統編程思惟
同步式 會執行內存換頁,cpu的緩存會被清空,從新讀取內存
Node.js的事件循環機制
(1) Node.js在何時進入事件循環呢?
Node.js程序是由事件循環開始,到事件循環結束,全部的邏輯都是事件的回調函數。
(2) 如何使用自定義事件呢?
事件的回調函數在執行的過程當中,可能會發出IO請求或直接發射(emit)事件,執行完畢後再返回事件循環。
模塊(Module)和包(Package)
不一樣的功能組件,劃分爲不一樣的模塊
模塊的定義十分簡單,接口也十分簡單。它的意義就是將類聚的方法或變量限定在私有的做用域中,同時支持引入和導出功能以便順暢的連接上下游依賴
例如:
var http = require('http') // 其中http是Node.js的一個核心模塊,經過require函數獲取這個模塊,而後使用其中的對象
Node.js提供了exports和require兩個對象,其中exports是模塊公開的接口,require用於從外部獲取一個模塊的接口,即獲取模塊的exports對象
一般使用module.exports,由於在exports對象是用過形參的方式傳入的,直接賦值形參會改變形參的引用,單並不能改變做用域外的值
二、包
包是在模塊基礎上更深一步的抽象,Node.js的包相似於C/C++的函數庫或者java的類庫,它講某個獨立的功能封裝起來,用於發佈、更新、依賴管理的版本控制。開發了npm來解決包的發佈和獲取需求
咱們使用這種方法能夠把文件夾封裝成一個模塊,即所謂的包。包一般是一些模塊的集合,在模塊的基礎上提供了更高層的抽象,至關於提供了一些固定接口的函數庫,經過定製package.json,咱們能夠建立更復雜、更完善、更符合規範的包用於發佈。
文件操做
Nodejs 中的 fs 模塊用來對本地文件進行操做。文件的I/O是由標準POSIX函數封裝而成。須要使用require('fs')訪問這個模塊。全部的方法都提供了異步和同步兩種方式。
fs 模塊中提供的方法能夠用來執行基本的文件操做,包括讀、寫、重命名、移動、建立和刪除目錄以及獲取文件元數據等。每一個操做文件的方法都有同步和異步兩個版本。
異步操做的版本都會使用一個回調方法做爲最後一個參數。當操做完成的時候,該回調方法會被調用。而回調方法的第一個參數老是保留爲操做時可能出現的異常。若是操做正確成功,則第一個參數的值是 null 或 undefined
var fs = require('fs'); 1.1. 讀取文件 var fs = require('fs'); 1.1.1、 fs.readFile(filename,[encoding],[callback(error,data)]) fs.readFile('book.txt', 'utf-8', (err, data) => { if (err) { throw err; } console.log(data); 1.1.2、 fs.readFileSync(filename,[encoding]) try { var data = fs.readFileSync('book.txt', 'utf-8'); console.log(data); } catch (e) { throw e; //文件不存在,或者權限錯誤 } 1.1.3、 fs.createReadStream(filename,[options]) var stream = fs.createReadStream('book.txt'); var data = ''; stream.on('data', (trunk) => { data += trunk; }); stream.on('end', () => { console.log(data); }); 1.1.4、 readLine var readline = require('readline'); var fs = require('fs'); var rl = readline.createInterface({ input: fs.createReadStream('book.txt') }); rl.on('line', (line) => { console.log('Line from file:' + line); }) 1.2、文件寫入 1.2.一、 fs.writeFile(filename, [callback(error)]) //若是文件不存在,會自動建立 fs.writeFile('name.txt', 'I am the man', (error) => { if(error){ console.log(error); } }) 1.2.2、fs.writeFileSync(file,[data]) try { fs.writeFileSync('timer.txt', 'JesseFu is the best'); } catch (e) { console.log(e); } 1.2.3、fs.createWriteStream(path[,option]) var streamWrite = fs.createWriteStream('fuguoliang.txt'); streamWrite.write('fuguoliang\r\n', (error) => { console.log(error); }); 1.2.四、fs.appendFile(file,data[,options],callback(err)) //追加文本 setInterval(() => { fs.appendFile('fuguoliang.txt', '\r\n ----Jesse ' + new Date().getSeconds()); }, 1000) 1.2.5、fs.appendFileSync(file,data[,options]) setInterval(() => { fs.appendFileSync('fuguoliang.txt', '\r\n ----what the hell... ' + new Date().getSeconds()) }, 1000) 驗證路徑是否存在 fs.exists(path,callback(isexists)) fs.existsSync(path) //返回true 或 false 獲取文件信息 fs.stat(path,callback(err,stats)) fs.statSync(path) //返回一個fs.stat實例 移動文件 移動/重命名 fs.rename(oldpath,newpath,callback); fs.renameSync(oldpath,newpath) 刪除文件 永久刪除/ fs.unlink(path,callback(err)); fs.unlinkSync(path); 建立一個目錄 (重名會報錯) fs.mkdir(path[,model],callback) fs.mkdirSync(path[,model]); 刪除一個空目錄 fs.rmdir(path,callback); fs.remdirSync(path); 讀取一個目錄 以數組形式展示 fs.readdir(path,callback(err,files)) fs.readdirSync(path); //返回files
不容易啊,客官能堅持看完,看來閣下也是性情中人啊。不過在這兒囉嗦了半天,也只能簡單瞭解,至於要更好的玩轉Nodejs還須要更多的學習交流。
言有盡而意無窮,於此,結束Nodejs的初次見面,印象不錯哦,客官有沒有觸到G點我不知道,我是會一直作下去
專業,由於專一
但願個人這篇筆記可以對客官有幫助,不勝榮幸,有好東西要分享一下嘍,多多指教 [抱拳]
推薦幾個學習Nodejs的網址:
http://nodejs.org/
http://www.oschina.net/p/nodejs/
http://www.ibm.com/developerworks/cn/opensource/os-nodejs/index.html