一、什么是node.js
Node.js 是一個基于 Chrome V8 引擎的 JavaScript 運行環(huán)境。 Node.js 使用了一個事件驅(qū)動、非阻塞式 I/O 的模型,使其輕量又高效。
Node.js是一個讓js運行在服務器端環(huán)境(類似于jvm)。
Node.js提供了大量的工具庫,使得js語言可以和操作系統(tǒng)交互(比如讀寫文件、新建子進程等)。從這個角度講,node是js的工具庫。
二、Node的常用命令
a、進入 REPL:
– node – node
--use_strict
· REPL 環(huán)境中:
– 類似 Chrome Developer Tools → Consoles
– 特殊變量下劃線(_)表示上一個命令的返回結(jié)果
– 通過 .exit 或執(zhí)行 process.exit() 退出 REPL 交互
b、運行js代碼
-在控制臺進入當前的js文件所在的目錄
-node ./*.js
三、Node的全局對象
Node中的全局對象是global。類似于客戶端 JavaScript 運行環(huán)境中的 window。
global屬性:指向全局對象global。
Buffer
__dirname
__filename
clearImmediate(immediateObject)
clearInterval(intervalObject)
clearTimeout(timeoutObject)
console
exports
global
module
process
require()
setImmediate(callback[, ...args])
setInterval(callback, delay[, ...args])
setTimeout(callback, delay[, ...args])
全局變量在所有模塊中均可使用。 但以下變量的作用域只在模塊內(nèi),詳見 module文檔:
__dirname
__filename
exports
module
require()
常用的全局對象
process
對象是一個全局變量,它提供當前 Node.js 進程的有關(guān)信息,以及控制當前 Node.js 進程。 因為是全局變量,所以無需使用 require()
。
常用屬性(詳細參考開發(fā)文檔)
a、process.argv process.argv
屬性返回一個數(shù)組,這個數(shù)組包含了啟動Node.js進程時的命令行參數(shù)。
b、process.stdout.write() 等價于沒有換行的console.log();
c、process.stdin.on('data',callback(input)) //注冊一個接受用戶輸入的事件。
四、Node中的異步回調(diào)函數(shù)實現(xiàn)
1 //node中的異步回調(diào)函數(shù)的實現(xiàn) 2 console.log("開始任務"); 3 setTimeout((filename) => { 4 var file=redfile(filename) //阻塞io的操作 讀文件 5 print(file) //打印文件內(nèi)容 6 }, 0); 7 console.log("結(jié)束任務"); 8 9 console.log("開始任務");10 11 //讀寫文件的函數(shù)12 function getfile(filename,callback){13 if(file可讀)14 //錯誤優(yōu)先的回調(diào)函數(shù):try/catch語句無法捕獲異步代碼中的錯誤15 callback(null,file);16 else 17 //錯誤優(yōu)先的回調(diào)函數(shù):try/catch語句無法捕獲異步代碼中的錯誤18 //異步的throw new Error('文件讀取失敗') 拋出的錯誤可能無法捕獲。19 callback(new Error('文件讀取失敗')) 20 }21 //使用函數(shù)22 getfile(filename,(err,file)=>{23 if(err)24 throw err;25 print(file);//打印文件內(nèi)容26 })27 console.log("結(jié)束任務");
五、Node中自定義事件
1 var event=require('events'); 2 //自定義事件的構(gòu)造函數(shù) 3 function Myevent(){ 4 //讓先創(chuàng)建的events對象繼承EventEmitter中的屬性 5 event.EventEmitter.call(this); 6 //時間注冊監(jiān)聽 7 this.register=function(){ 8 this.once('Myevent',function(){ 9 process.stdout.write('this is my event');10 })11 }12 }13 //繼承EventEmitter的方法14 Myevent.prototype=event.EventEmitter.prototype;15 //創(chuàng)建事件16 var myevent=new Myevent();17 //為事件注冊一個監(jiān)聽18 myevent.register();19 //發(fā)射事件20 myevent.emit('Myevent');
六、Node.js的事件機制
Node.js應用程序在一個單線程的事件驅(qū)動模型中運行。雖然Node.js在后臺實現(xiàn)了一個線程池來做工作,但是應用程序本身不具備多線程的任何概念。
在傳統(tǒng)的線程網(wǎng)絡(luò)模型中,請求進入一個Web服務器,并被分配給一個可用的線程,對于該請求的處理工作繼續(xù)在該線程上進行,直到請求完成并發(fā)出響應。
node.js不會在各個線程上執(zhí)行每個請求的所有工作,而是把工作添加到事件隊列中,然后通過一個單線程的事件循環(huán)從事件隊列中把工作提取出來執(zhí)行,事件循環(huán)會抓取事件隊列中最上層的工作,執(zhí)行它,先后抓取下一個找工作執(zhí)行,當事件隊列里的所有工作都被執(zhí)行完成時,node.js應用程序終止。
上面圖中有兩個請求GetFile和GetData.Node.js程序把兩個請求添加進事件隊列中,然后事件循環(huán)主線程會提取出第一個GetFile請求,執(zhí)行完成后執(zhí)行回調(diào)函數(shù),回調(diào)函數(shù)中的Open(file)和它的回調(diào)函數(shù)請求被添加進事件隊列中,事件循環(huán)從事件隊列中提取下一個GetData請求執(zhí)行,執(zhí)行完成后執(zhí)行回調(diào)函數(shù),后調(diào)函數(shù)中的Connect(file)和他的回調(diào)函數(shù)被加入事件隊列,這種情況會一直持續(xù)到事件隊列中沒有可提取的事件為止。
阻塞IO:停止當前線程的執(zhí)行等待回應,直到收到回應才繼續(xù)執(zhí)行,阻塞IO的例子有:請求文件、讀取數(shù)據(jù)庫、請求套接字、訪問遠程服務。
Node.js采用事件回調(diào)來避免對阻塞IO的等待。事件循環(huán)主線程會將阻塞IO的請求放入Node后臺的線程池中執(zhí)行,主線程可以處理其他的請求,當后臺線程處理完那個阻塞IO的請求,主線程執(zhí)行對應的回調(diào)函數(shù),如果回調(diào)函數(shù)中沒有阻塞IO的代碼,直接執(zhí)行返回,如果回調(diào)函數(shù)中包含阻塞IO的代碼,繼續(xù)放入事件循環(huán)的隊伍,等待事件循環(huán)執(zhí)行。