第四章 建議學(xué)習(xí)時間2小時  課程共10章

學(xué)習(xí)方式:詳細閱讀,并手動實現(xiàn)相關(guān)代碼

學(xué)習(xí)目標:此教程將教會大家 安裝Node、搭建服務(wù)器、express、mysql、mongodb、編寫后臺業(yè)務(wù)邏輯、編寫接口,最后完成一個完整的項目后臺,預(yù)計共10天課程。

 

node.js事件機制


 node.js是單線程,但是通過事件和回調(diào)支持并發(fā),可以實現(xiàn)非常高的性能。

node.js所有的API都是通過異步調(diào)用。第一堂課的時候,我們寫過一個同步和異步的示例(如下),當初說到:同步代碼先執(zhí)行完成,然后才執(zhí)行異步代碼。

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

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

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

而對于異步的多個代碼,它們的執(zhí)行順序是怎樣的呢?試試下面的代碼:

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

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

main.js中寫入如下代碼:

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

var fs = require("fs"); //node 內(nèi)置模塊可直接引入  fs:文件系統(tǒng)操作模塊fs.readFile("./a.txt","utf-8",function(err,data){  //讀取文件
    if(err) throw err;
    console.log(data);
});
setTimeout(function(){
    console.log("定時器打?。?quot;);
},0);

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

 使用 node 運行  main.js后,你會發(fā)現(xiàn)定時器的先打印,(增加定時器的觸發(fā)時間,你會發(fā)現(xiàn),打印的順序會改變。)

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

具體的異步代碼執(zhí)行順序,是由node.js內(nèi)部機制控制的,我們很難準確預(yù)知。這里給大家介紹一下node.js的事件模型:

Node.js 使用事件驅(qū)動模型,當web server接收到請求,就把它關(guān)閉然后進行處理,然后去服務(wù)下一個web請求。

當這個請求完成,它被放回處理隊列,當?shù)竭_隊列開頭,這個結(jié)果被返回給用戶。

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

在事件驅(qū)動模型中,會生成一個主循環(huán)來監(jiān)聽事件,當檢測到事件時觸發(fā)回調(diào)函數(shù)。

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

 

 

回調(diào)函數(shù)


 

回調(diào)函數(shù)就是將一個函數(shù)作為另一個函數(shù)的參數(shù)傳入,作為另一個函數(shù)內(nèi)部執(zhí)行的函數(shù)。

我們上面示例中的文件讀取方法中,第三個參數(shù)是一個回調(diào)函數(shù),當文件讀取完成,就會自動調(diào)用這個函數(shù)。

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

 

上面的回調(diào)是封裝好的,那么我們自己來寫一個回調(diào)函數(shù)的實現(xiàn)樣子:

創(chuàng)建 一個js文件,寫入如下代碼:

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

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);
    }
})

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

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

 

 異步IO操作


 我們前面講的文件讀取的方式是一次性全部讀取,當文件過大的時候,一次性讀取不僅緩慢,而且影響用戶體驗,那么怎么實現(xiàn)分步讀取呢,

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

具體實現(xiàn):

我們創(chuàng)建一個文件讀取流,先上代碼 

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

var fs = require("fs");var  data = "";  //聲明一個空字符串來存讀取的數(shù)據(jù)var rs = fs.createReadStream("a.txt");

rs.setEncoding("utf-8");//監(jiān)聽當有數(shù)據(jù)流入的時候rs.on("data",function(chunc){
    data += chunc;       //將讀取的數(shù)據(jù)拼接到data上。
    console.log("..."); //讀的過程中,我們打印三個點。});

rs.on("end",function(){
    console.log("沒有數(shù)據(jù)了")
});

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

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

代碼中,創(chuàng)建main3.js寫入上面的代碼,使用 reateReadStream創(chuàng)建讀取流對象,在對象上使用on監(jiān)聽“data”讀取數(shù)據(jù)的事件,每讀取一段數(shù)據(jù),就會觸發(fā)這個事件,當讀取完畢, 就會觸發(fā)“end”事件。

執(zhí)行main3.js,我們就可以看到下面打印的結(jié)果,從打印的多行"..."中,我們就可以看出,讀取了多次才讀完。

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

 

 

將讀取到的數(shù)據(jù),慢慢的寫入 b.txt中

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

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

 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 //監(jiān)聽當有數(shù)據(jù)流入的時候 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("沒有數(shù)據(jù)了");16     ws.end();                 //關(guān)閉寫入流17 });

iOS培訓(xùn),Swift培訓(xùn),蘋果開發(fā)培訓(xùn),移動開發(fā)培訓(xùn)

這樣我們異步的讀取和寫入文件就實現(xiàn)了

 

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

http://www.cnblogs.com/chengduxiaoc/p/6992329.html