Nodejs編程基礎(chǔ)

這是一系列Nodejs實戰(zhàn)第一季后的整理筆記,為了快速查找及記錄

Node 功能的組織及重用

1.1.1、創(chuàng)建模塊

定義Node模塊
currency.js

/*exports 對象上只設(shè)定了兩個屬性。也就是說引入這個模塊的代碼只能訪問到 canadianToUS
和 USToCanadian 這兩個函數(shù)。而變量 canadianDollar 作為私有變量僅作用在 canadianToUS
和 USToCanadian 的邏輯內(nèi)部,程序不能直接訪問它。*/
var canadianDollar = 0.91;
functon roundTwoDecimals(amount){
  return Math.round(amount * 100)/100;
}
exports.canadianToUS = funtion(canadian){
  return roundTwoDecimals(candian * canadianDollar);
}
exports.USToCanadian = function(us){
  return roundTwoDecimals(us/canadianDollar);
}

引入一個模塊
test-currency.js

var currency = require('./currency');
console.log(currency.canadianToUS(50));
console.log(currency.USToCanadina(30));

1.1.2 用module.exports微調(diào)模塊的創(chuàng)建

module.exports返回一個Currency的構(gòu)造函數(shù)(類似于class)

/*
最終在程序里導(dǎo)出的是 module.exports 。 exports 只是對 module.exports 的一個全
局 引 用 , 最 初 被 定 義 為 一 個 可 以 添 加 屬 性 的 空 對 象 。 所 以 exports.myFunc 只 是
module.exports.myFunc 的簡寫
*/
var Currency = function(canadianDollar){
  this.canadianDollar = canadianDollar;
}
Currency.prototype.roundTwoDecimals = function(amount){
  return Math.round(amount * 100) / 100;
}
Currency.prototype.canadianToUS = function(canadian){
  return this.roundTwoDecimals(canadian * this.canadianDollar);
}
Currency.prototype.USToCanadian = function(us){
  return this.roundTwoDecimals(us / this.canadianDollar);
}
module.exports = exports = Currency;

1.2 異步編程技術(shù)

1.2.1 用回調(diào)處理一次性事件
回調(diào)是一個函數(shù),它被當(dāng)做參數(shù)傳給異步函數(shù)
實現(xiàn)功能

  • 異步獲取存放在JSON文件中的文章標(biāo)題
  • 異步獲取簡單的HTML模板
  • 把那些標(biāo)題組裝到HTML頁面中
  • 把HTML頁面發(fā)送給用戶
    title.json
[
  "node",
  "利于",
  "服務(wù)器"
]

template.html

<!doctype html>
<html>
  <head></head>
  <body>
    <h1>Lastest Posts</h1>
    <ul>
      <!--會被替換為標(biāo)提-->
      <li>%</li>
    </ul>
  </body>
</html>

blog_recent.js

var http = require('http');
var fs = require('fs');
var server = http.createServer(function(req,res){
    getTitles(res);
}).listen(3000);
function getTitles(res){
    fs.readFile('./title.json',function(err,data){
        if(err) return hadError(err,res);
        getTemplate(JSON.parse(data.toString()),res);
    });
}
function getTemplate(titles,res){
    fs.readFile('./template.html',function(err,data){
        if(err) return hadError(err,res);
        formatHtml(titles,data.toString(),res);
    })
}
function formatHtml(titles,tmpl,res){
    var html = tmpl.replace('%',titles.join('<li></li>'));
    res.writeHead(200,{'Content-Type':'text/html'});
    res.end(html);
}
function hadError(err,res){
    console.log(err);
    res.end('Server Error');
}

1.2.2 用事件發(fā)射器處理重復(fù)性事件
echo服務(wù)器處理重復(fù)性事件的簡單案例
用on方法響應(yīng)事件
echo_server.js

var net = require('net');
var server = net.createServer(function(socket){
  #當(dāng)讀取到新數(shù)據(jù)時處理的data事件 once 只響應(yīng)一次
  socket.once('data',function(data){
      socket.write(data);//數(shù)據(jù)被寫回到客戶端
    });
});
server.listen(8888);

運行 node echo_server.js
新打終端 telnet 127.0.0.1:8888

Paste_Image.png

簡易聊天室
easy_chat.js

var events = require('events');
var net = require('net');
#設(shè)置
var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};
#綁定發(fā)射器
channel.on('join',function(id,client){
  #添加join事件的監(jiān)聽器,保存用戶的client對象,以便程序可以將數(shù)據(jù)發(fā)送給用戶
  this.clients[id] = client;
  #連接人數(shù)
  var num = "Welcome!\n" + 'Guest online:' + this.listeners('broadcast').length;
  client.write('num is '+ num);
  this.subscriptions[id] = function(senderId,message){
    #忽略發(fā)出這一廣播數(shù)據(jù)的用戶
    if(id != senderId){
      this.clients[id].write(id +':'+ message);
    }
  }
  #添加一個專門針對當(dāng)前用戶的broadcast事件監(jiān)聽器
  this.on('broadcast',this.subscriptions[id]);
});
#創(chuàng)建一個在用戶斷開連接時能打掃戰(zhàn)場的監(jiān)聽器
channel.on('leave',function(id){
  channel.removeListener('broadcast',this.subscriptions[id]);
  channel.emit('broadcast',id,id+' has left the chat.\n');
});
#關(guān)閉聊天服務(wù) 但不關(guān)閉服務(wù)器
channel.on('shutdown',function(){
  channel.emit('broadcast','',"Chat has shut down.\n");
  channel.removeAllListeners('broadcast');
})
#增加監(jiān)聽器數(shù)量 channel 是事件發(fā)射器
channel.setMaxListeners(50);
#創(chuàng)建一個錯誤接聽器
var server = net.createServer();
server.on('connection',function(client){
  var id = client.remoteAddress + ':' + client.remotePort;
  #連接時
  console.log('connect success');
  channel.emit('join',id,client);
  client.on('data',function(data){
    data = data.toString();
    if(data == "shutdown\r\n"){
      channel.emit('shutdown');
    }
    channel.emit('broadcast',id,data);
  });
  #用戶斷開連接時發(fā)出leave事件
  client.on('close',function(){
    channel.emit('leave',id);
  });
});
server.listen(8888);

用匿名函數(shù)保留全局變量的值

/*異步 color在不斷變化 */
function asyncFunction(callback){
  setTimeout(callback,200);
}
var color = 'blue';
asyncFunction(function(){
  console.log('no function is color ' + color);
});
/*
* 解決方法
* 用javascript閉包可以“凍結(jié)”color的值
* 對asyncFunction的調(diào)用被封裝到以color為參數(shù)的匿名函數(shù)中
*/
(function(color){
  asyncFunction(function(){
    console.log("function is color " + color);
  });
})(color);
var color = 'green';

1.3 異步邏輯順序化

用Nimble的流程控制

#安裝Nimble
npm install nimble

Nimble工具實現(xiàn)串行

var flow = require('nimble');
flow.series([
    function(callback){
        setTimeout(function(){
            console.log('I exec first.');
            callback();
        },1000);
    },
    function(callback){
        setTimeout(function(){
            console.log('I exec second.');
            callback();
        },500);
    },
    function(callback){
        setTimeout(function(){
            console.log('I exec third.');
            callback();
        },100);
    }
]);

1.3.2 實現(xiàn)串行化流程控制
將預(yù)先需要按流程執(zhí)行的任務(wù)添加到數(shù)組中

/*
* 串行執(zhí)行
* 并行下載后 串行執(zhí)行歸檔
*/

var flow = require('nimble');
var exec = require('child_process').exec;

//下載文件輔助函數(shù)
function downloadNodeVersion(version,destination,callback){
    var url = "http://nodejs.org/dist/node-v" + version + ".tar.gz";
    var filepath = destination + '/' + version + '.tgz';
    exec('curl '+url+' > '+ filepath,callback);
}
//按照順序執(zhí)行串行化任務(wù) series 串行的
flow.series([
    function(callback){
        //parallel 平行的 并列的
        flow.parallel([
            function(callback){
                console.log('Downloading Node v0.4.6....');
                downloadNodeVersion('0.4.6','/tmp',callback);
            },
            function(callback){
                console.log('Downloading Node v0.4.7....');
                downloadNodeVersion('0.4.7','/tmp',callback);
            }
        ],callback);
    },
    function(callback){
        //創(chuàng)建遞歸文件
        console.log('Creating archive of download files');
        exec('tar cvf node_distros.tar /tmp/0.4.6.tgz /tmp/0.4.7.tgz',
        function(error,stdout,stderr){
            console.log('All done!');
            callback();
        }
    )
}
]);

1.3.3 并行流程控制

/*
* 并行化流程控制
* 計算文件中單詞出現(xiàn)的次數(shù)
*/
var fs = require('fs');
var completedTakes = 0;
var takes = [];
var wordCounts = {};
var fileDir = './text';

//所有的任務(wù)都完成后
function checkIfComplate(){
  completedTakes++;
  if(completedTakes == takes.length){
    for(var index in wordCounts){
      console.log(index + ': '+wordCounts[index]);
    }
  }
}

//計算文件中出現(xiàn)的單詞數(shù)
function countWordsInText(text){
  var words = text.toString().toLowerCase().split(' ');
  console.log(words);

    for(var index in words){
      word = words[index];
      if(word){
        wordCounts[word] = (wordCounts[word])?wordCounts[word]+1:1;
      }

    }
}

//讀取文件
fs.readdir(fileDir,function(err,files){
  if(err) throw err;
  for(var index in files){
    var take = (function(file){
      return function(){
        fs.readFile(file,function(err,text){
          if(err) throw err;
          countWordsInText(text);
          checkIfComplate();
        });
      }
    })(fileDir +'/'+ files[index]);
    //加入排序中
    takes.push(take);
  }
  for(var index in takes){
    takes[index]();
  }
});

水平一般,能力有限。隨手記憶~~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容