node.js零基礎詳細教程(4):node.js事件機制、node非同步IO操作

來源:互聯網
上載者:User

標籤:三個點   樣本   blog   詳細   模組   UI   檔案格式   函數   reads   

第四章 建議學習時間3小時  課程共10章

學習方式:詳細閱讀,並手動實現相關代碼

學習目標:此教程將教會大家 安裝Node、搭建伺服器、express、mysql、mongodb、編寫後台商務邏輯、編寫介面,最後完成一個完整的項目後台,預計共10天課程。

 

node.js事件機制

 node.js是單線程,但是通過事件和回調支援並發,可以實現非常高的效能。

node.js所有的API都是通過非同步呼叫。第一堂課的時候,我們寫過一個同步和非同步樣本(如下),當初說到:同步代碼先執行完成,然後才執行非同步代碼。

setTimeout(function(){    console.log(1000000000);},0);for(var i=0; i<1000; i++){    console.log(i);}

而對於非同步多個代碼,它們的執行順序是怎樣的呢?試試下面的代碼:

今天的代碼我們放到一個新的檔案夾 中,為了完成下面的檔案讀取,我們需要提前準備一個a.txt的檔案(注意:檔案格式最好是uft-8)

main.js中寫入如下代碼:

var fs = require("fs"); //node 內建模組可直接引入  fs:檔案系統操作模組fs.readFile("./a.txt","utf-8",function(err,data){  //讀取檔案    if(err) throw err;    console.log(data);});setTimeout(function(){    console.log("定時器列印!");},0);

 使用 node 運行  main.js後,你會發現定時器的先列印,(增加定時器的觸發時間,你會發現,列印的順序會改變。)

具體的非同步代碼執行順序,是由node.js內部機制控制的,我們很難準確預知。這裡給大家介紹一下node.js的事件模型:

Node.js 使用事件驅動模型,當web server接收到請求,就把它關閉然後進行處理,然後去服務下一個web請求。

當這個請求完成,它被放回處理隊列,當到達隊列開頭,這個結果被返回給使用者。

這個模型非常高效可擴充性非常強,因為webserver一直接受請求而不等待任何讀寫操作。(這也被稱之為非阻塞式IO或者事件驅動IO)

在事件驅動模型中,會產生一個主迴圈來監聽事件,當檢測到事件時觸發回呼函數。

 

 

回呼函數

 

回呼函數就是將一個函數作為另一個函數的參數傳入,作為另一個函數內部執行的函數。

我們上面樣本中的檔案讀取方法中,第三個參數是一個回呼函數,當檔案讀取完成,就會自動調用這個函數。

fs.readFile("./a.txt","utf-8",function(err,data){  //讀取檔案    if(err) throw err;    console.log(data);});

 

上面的回調是封裝好的,那麼我們自己來寫一個回呼函數的實現樣子:

建立 一個js檔案,寫入如下代碼:

function fn01(data,callback){    if(data){        callback("",data);    }else{        var err = new Error("錯誤了");        callback(err)    }}fn01("aa",function(err,data){    if(err){        console.log("錯誤"+err);    }else{        console.log(data);    }})

上面代碼是回呼函數的標準模型,我們在調用 fn01的時候,傳入了兩個參數,第一個是字串,第二個是一個回呼函數,當參數傳入以後。我們來看fn01的主方法,方法中檢測第一個參數的存在情況來,然後執行callback方法,也就是執行了當參數傳入的那個方法。

 

 非同步IO操作

 我們前面講的檔案讀取的方式是一次性全部讀取,當檔案過大的時候,一次性讀取不僅緩慢,而且影響使用者體驗,那麼怎麼實現分步讀取呢,

這就得使用到非同步IO的操作,像水流一樣流出一段取得一段。

具體實現:

我們建立一個檔案讀取流,先上代碼 

var fs = require("fs");var  data = "";  //聲明一個Null 字元串來存讀取的資料var rs = fs.createReadStream("a.txt");rs.setEncoding("utf-8");//監聽當有資料流入的時候rs.on("data",function(chunc){    data += chunc;       //將讀取的資料拼接到data上。    console.log("..."); //讀的過程中,我們列印三個點。});rs.on("end",function(){    console.log("沒有資料了")});

我們將 a.txt中的內容增加,以讓讀取時間變長,

代碼中,建立main3.js寫入上面的代碼,使用 reateReadStream建立讀取流對象,在對象上使用on監聽“data”讀取資料的事件,每讀取一段資料,就會觸發這個事件,當讀取完畢, 就會觸發“end”事件。

執行main3.js,我們就可以看到下面列印的結果,從列印的多行"..."中,我們就可以看出,讀取了多次才讀完。

 

 

將讀取到的資料,慢慢的寫入 b.txt中

修改mai3.js中的代碼為如下,增加了下面代碼的  4/10/16行,4行表示建立一個寫入流(如果寫入的檔案不存在,會自動建立一個檔案),10行表示往檔案寫入東西,16行表示關閉寫入流。

 1 var fs = require("fs"); 2  3 var rs = fs.createReadStream("a.txt"); 4 var ws = fs.createWriteStream("b.txt"); //寫入流 5 rs.setEncoding("utf-8"); 6  7 //監聽當有資料流入的時候 8 rs.on("data",function(chunc){ 9     console.log("..."); //讀的過程中,我們列印三個點。10     ws.write(chunc,"utf-8"); //向檔案寫入東西11 });12 13 14 rs.on("end",function(){15     console.log("沒有資料了");16     ws.end();                 //關閉寫入流17 });

這樣我們非同步讀取和寫入檔案就實現了

 

好,今天就講這麼多,明天將講解:express 路由。

 

node.js零基礎詳細教程(4):node.js事件機制、node非同步IO操作

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.