初識node.js

1、概念類

一、node.js是什麼

node.js不是一種獨立的語言,與php既是語言也是平臺不一樣,也不是JavaScript的框架,更不是瀏覽器的庫。node.js是一個讓JavaScript運行在服務端的開發平臺。php

二、node.js能作什麼

JavaScript是由客戶端而產生,node.js爲網絡而生html

具備複雜邏輯的網站node

基於社交網站的大web的應用c++

web scoket服務器web

TCP/UDP套接字應用程序chrome

命令行工具npm

交互式終端程序編程

三、異步式I/O與事件驅動

node.js最大的特性就是採用異步式I/O與事件驅動的架構設計。對於高併發的解決方案,傳統的架構是多線程模型,也就是爲每一個業務邏輯提供一個系統線程,經過系統線程切換來彌補同步式I/O調用時的事件開銷。node.js使用的單線程模型,在執行的過程當中會維護一個事件隊列,程序在執行時在進入時間循環等待下一個事件到來。json

普通:res = db.query("select * form user")數組

     res.output();

node.js: res = db.query("select * form user",function(res){

      res.output();

       })

程序會自動往下執行

四、瀏覽器引擎革命

Google chrome的引擎是V8,node.js的引擎引用的就是V8,因此它快

五、部署node.js的環境

node.js官方,http://nodejs.org 下載安裝包,安裝後,打開cmd的的dos窗口,運行node

2、node入門

一、Hello World

打開一個文本編輯器,其中輸入console.log("Hello World"),並保存爲test.js

打開dos窗口進入該文件的目錄運行 node test.js,執行則能夠看到輸出的Hello World

二、node.js命令行工具

node -v  輸出版本號

node -e  eval script  eval("console.log('哈哈')")  例:node -e "console.log('哈哈')";直接執行

node  直接進入編譯模式  console.log("111")  第一行是輸出,第二行是返回值

三、創建HTTP服務器

創建一個app.js

1 var http = require("http");
2 http.createServer(function(req,res){
3    res.writeHead(200,{'Content-Type':'text/html'});
4    res.write('<h1>Node.js</h1>');
5    res.end('<p>PCAT</p>');   
6 }).listen(3000);
7 console.log('HTTP server is listening at port 3000');

接下來,node app.js  打開瀏覽器訪問http://localhost:3000便可,這樣就部署了一個web

四、調試代碼

npm install supervisor -g(在nodejs\node_modules\npm目錄下)安裝supervisor來控制調試代碼,不須要每次中止重啓node.js的服務

使用supervisor app.js啓動

3、node.js異步式IO與事件式編程

node.js最大的特性就是異步式I/O與事件緊密結合的編程模式。這種模式與傳統的同步式IO線性的編程思路有很大的不一樣,由於控制流很大程度上要靠事件和回調函數來組織,一個邏輯要拆分爲若干個單元格

一、同步式I/O或阻塞式I/O

線程在執行中若是遇到磁盤讀寫或網絡通訊,一般要耗費較長時間。這時操做系統會剝奪這個線程的CPU控制權,使其暫停執行,同時把資源讓給其餘的工做線程這種線程調度方式稱爲阻塞,當I/O操做完畢時,操做系統將這個線程的阻塞狀態解除,回覆其對CPU的控制權,令其繼續執行

二、異步式I/O或阻塞式I/O

針對全部I/O操做不採用阻塞策略,當線程遇到I/O操做時,不會以阻塞的方式等待I/O操做的完成或數據的返回,二隻是將IO請求發送給操做系統,繼續執行下一條語句,當操做系統完成IO操做時,以事件的形式通知執行IO操做的線程,線程會在特定時候處理這個事件,爲了處理異步IO,線程必須有事件循環,不斷地檢查有沒有未處理的時間,依次予以處理

三、非阻塞和阻塞模式的區別

非阻塞模式下,一個線程永遠在執行計算操做,這個線程所使用的CPU核心利用率永遠是100%,IO以事件的方式通知

阻塞模式下,多線程每每能提升系統吞吐量,由於一個線程阻塞還有其餘線程在工做,多線程可讓CPU資源不被阻塞中的線程浪費

四、同步式IO與異步式IO的區別

同步式IO(阻塞式)

利用多線程提供吞吐量

經過事件片分隔和線程調度利用多核CPU

須要由操做系統調度多線程使用多核CPU

難以充分利用CPU資源

內存軌跡大,數據局部性弱

符合線性的編程思惟

 

異步式IO(非阻塞)

單線程便可實現高吞吐量

經過功能劃分利用多核

能夠將但相處綁定到單核CPU

能夠充分利用CPU資源

內存軌跡小,數據局部性強

不符合傳統編程思惟

 4、回調函數與事件

一、回調函數

1.一、異步式讀取文件

1 var fs = require("fs");
2 var data = fs.readFile("file.txt","UTF-8",function(err,data){
3     if(err){
4         console.log("read file err");
5     }else{
6         console.log(data);
7     }
8 })
9 console.log("end,");

結果:end

     文件內容

1.二、同步式讀取文件

1 var fs = require("fs"); 2 var data = fs.readFileSync("file.txt","UTF-8"); 3 console.log(data); 4 console.log("end");

結果:文件內容

    end

1.三、分析

調用時所作的工做只是將異步式IO請求發送給了操做系統,而後當即返回並執行後面的語句,執行完之後進入事件循環監聽事件,當fs接收到IO請求完成的事件時。事件循環會主動調用回調函數完成後續工做。同步則是阻塞等待文成後,繼續執行

二、事件

2.一、普通事件的使用

//聲明事件對象
var EventEmitter = require("events").EventEmitter;
var event = new EventEmitter();
//註冊事件
event.on("some_event",function(){
   console.log(111); 
})
//觸發事件
setTimeout(function(){
   event.emit("some_event"); 
},3000)

2.二、node.js的事件循環機制

node.js在何時進入事件循環呢

node.js程序是由事件循環開始,到事件循環結束,全部的邏輯都是事件的回調函數

如何使用自定義事件呢?

事件的回調函數在執行過程當中,可能會發出IO請求或直接發射(emit)事件,執行完畢後再返回事件循環

5、模塊和包

概念:模塊和包是node.js最重要的支柱。開發一個具備必定規模的程序不願只用一個文件,一般須要把各個功能拆分、分裝、而後組合起來。模塊正是爲了實現這種方式而誕生,在瀏覽器JavaScript中,腳本模塊的拆分和組合一般使用html的script標籤來實現,node.js提供了require函數來調用其餘模塊,並且模塊都是基於文件,模塊和包的區別是透明的,常常不作區分

一、模塊

1.一、什麼是模塊

模塊和文件是一一對應的。一個node.js文件就是一個模塊,這個文件多是JavaScript代碼、json或者編譯過的c/c++擴展。

var http = require("http"),其中http是node.js的一個核心模塊,經過require函數獲取這個模塊,而後使用其中的對象

1.二、建立及加載模塊

(1)建立模塊

node.js提供了exports和require兩個對象,其中exports是模塊公開的接口,require用於從外部獲取一個模塊的接口,即獲取模塊的exports對象

module.js

1 var name;
2 exports.setName = function(theName){
3     name = theName;
4 }
5 exports.sayHello = function(){
6     console.log("hello"+name);
7 }

getModule.js

1 var myModule = require("./module");
2 myModule.setName("wang er");
3 myModule.sayHello();

(2)單次加載

上面的例子相似建立一個對象,但實際上和對象又有本質的區別,由於require不會重複加載模塊,不管調用多少次require,獲取的模塊都是同一個

getModule2.js

1 var myModule1 = require("./module");
2 myModule1.setName("wang wu");
3 var myModule2 = require("./module");
4 myModule2.setName("hello world");
5 myModule1.sayHello();

(3)覆蓋exports

有時咱們想把一個對象封裝到模塊中

定義模塊:singleobject.js

 1 function hello(){
 2     var name;
 3     this.setName = function(theName){
 4         name = theName;
 5     }
 6     this.sayHello = function(){
 7         console.log("hello"+name);
 8     }
 9 };
10 module.exports = hello;

引入模塊使用:getsingleobject.js

1 var hello = require("./singleobject");
2 var he = new hello();
3 he.setName("sugar");
4 he.sayHello();
5 var he2 = new hello();
6 he2.setName("txy");
7 he2.sayHello();

exports自己僅僅是一個普通的空對象,即{},它是專門用來聲明接口

二、建立包

2.一、包的概念

包是在模塊基礎上更深一步的抽象,node.js的包相似於c/c++的函數庫或者Java的類庫,它將某個獨立的功能封裝起來,用於發佈、更新、依賴管理的版本控制。開發了npm來解決包的發佈和獲取需求。

2.二、如何建立一個包

commonJS規範的包具有如下特徵:

  package.json必須在包的頂層目錄下

  二進制文件應該在bin目錄下

  JavaScript代碼應該在lib目錄下

  文檔應該在doc目錄下

  單元測試應該在test目錄下

Node.js對包要求沒有那麼嚴格,只要頂層目錄下有package.json,並符合基本規範便可

(1)做爲文件夾的模塊

somepackage文件夾(最簡單的包,就是做爲文件夾的模塊)

建立一個文件夾somepackage,裏面有一個index.js,裏面提供一個方法sayHello()

var somepackage = require("./somepackage");

somepackage.sayHello();

使用這種方法能夠把文件夾封裝成一個模塊,即包。包一般是一些模塊的集合,在模塊的基礎上提供了更高層的抽象,至關於提供了一些固定接口的函數庫,經過定製package.json,咱們能夠建立更符合規範的包進行發佈。

(2)package.json

在somepackage文件夾下,咱們建立一個package.json的文件,內容{"main":"./lib/index.js"}

node.js在調用某個包時,會檢查包中package.json文件的main字段,將其做爲包的接口模塊,若是package.json或main字段不存在,會尋找index.js或index.code做爲包的接口

package.json的規範屬性:

name:包的名稱,必須是惟一

description:包的簡要說明

version:符合語義化版本識別規範的版本字符串

keywords:關鍵字數據,一般用於搜索

maintainers:維護者數組,每一個元素要包含name、email、web可選字段

contributes:貢獻者數組,格式與maintainers相同。包的做者應該是貢獻者數據的第一個元素

bugs:提交bug的地址,能夠是網址或者是電子郵件地址

licenses:許可證數組,每一個元素要包含type、url字段

repositories:倉庫託管地址數組,每一個元素要包含type、url、和path、字段

dependencies:包的依賴,一個關聯數組,由包名稱和版本號組成

相關文章
相關標籤/搜索