Nodejs编程基础

这是一系列Nodejs实战第一季后的整理笔记,为了快速查找及记录

Node 功能的组织及重用

1.1.1、创建模块

定义Node模块
currency.js

/*exports 对象上只设定了两个属性。也就是说引入这个模块的代码只能访问到 canadianToUS
和 USToCanadian 这两个函数。而变量 canadianDollar 作为私有变量仅作用在 canadianToUS
和 USToCanadian 的逻辑内部,程序不能直接访问它。*/
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微调模块的创建

module.exports返回一个Currency的构造函数(类似于class)

/*
最终在程序里导出的是 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 异步编程技术

1.2.1 用回调处理一次性事件
回调是一个函数,它被当做参数传给异步函数
实现功能

  • 异步获取存放在JSON文件中的文章标题
  • 异步获取简单的HTML模板
  • 把那些标题组装到HTML页面中
  • 把HTML页面发送给用户
    title.json
[
  "node",
  "利于",
  "服务器"
]

template.html



  
  
    

Lastest Posts

  • %

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('
  • ')); res.writeHead(200,{'Content-Type':'text/html'}); res.end(html); } function hadError(err,res){ console.log(err); res.end('Server Error'); }

    1.2.2 用事件发射器处理重复性事件
    echo服务器处理重复性事件的简单案例
    用on方法响应事件
    echo_server.js

    var net = require('net');
    var server = net.createServer(function(socket){
      #当读取到新数据时处理的data事件 once 只响应一次
      socket.once('data',function(data){
          socket.write(data);//数据被写回到客户端
        });
    });
    server.listen(8888);
    

    运行 node echo_server.js
    新打终端 telnet 127.0.0.1:8888

    Nodejs编程基础_第1张图片
    Paste_Image.png

    简易聊天室
    easy_chat.js

    var events = require('events');
    var net = require('net');
    #设置
    var channel = new events.EventEmitter();
    channel.clients = {};
    channel.subscriptions = {};
    #绑定发射器
    channel.on('join',function(id,client){
      #添加join事件的监听器,保存用户的client对象,以便程序可以将数据发送给用户
      this.clients[id] = client;
      #连接人数
      var num = "Welcome!\n" + 'Guest online:' + this.listeners('broadcast').length;
      client.write('num is '+ num);
      this.subscriptions[id] = function(senderId,message){
        #忽略发出这一广播数据的用户
        if(id != senderId){
          this.clients[id].write(id +':'+ message);
        }
      }
      #添加一个专门针对当前用户的broadcast事件监听器
      this.on('broadcast',this.subscriptions[id]);
    });
    #创建一个在用户断开连接时能打扫战场的监听器
    channel.on('leave',function(id){
      channel.removeListener('broadcast',this.subscriptions[id]);
      channel.emit('broadcast',id,id+' has left the chat.\n');
    });
    #关闭聊天服务 但不关闭服务器
    channel.on('shutdown',function(){
      channel.emit('broadcast','',"Chat has shut down.\n");
      channel.removeAllListeners('broadcast');
    })
    #增加监听器数量 channel 是事件发射器
    channel.setMaxListeners(50);
    #创建一个错误接听器
    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);
      });
      #用户断开连接时发出leave事件
      client.on('close',function(){
        channel.emit('leave',id);
      });
    });
    server.listen(8888);
    

    用匿名函数保留全局变量的值

    /*异步 color在不断变化 */
    function asyncFunction(callback){
      setTimeout(callback,200);
    }
    var color = 'blue';
    asyncFunction(function(){
      console.log('no function is color ' + color);
    });
    /*
    * 解决方法
    * 用javascript闭包可以“冻结”color的值
    * 对asyncFunction的调用被封装到以color为参数的匿名函数中
    */
    (function(color){
      asyncFunction(function(){
        console.log("function is color " + color);
      });
    })(color);
    var color = 'green';
    

    1.3 异步逻辑顺序化

    用Nimble的流程控制

    #安装Nimble
    npm install nimble
    

    Nimble工具实现串行

    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 实现串行化流程控制
    将预先需要按流程执行的任务添加到数组中

    /*
    * 串行执行
    * 并行下载后 串行执行归档
    */
    
    var flow = require('nimble');
    var exec = require('child_process').exec;
    
    //下载文件辅助函数
    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);
    }
    //按照顺序执行串行化任务 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){
            //创建递归文件
            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 并行流程控制

    /*
    * 并行化流程控制
    * 计算文件中单词出现的次数
    */
    var fs = require('fs');
    var completedTakes = 0;
    var takes = [];
    var wordCounts = {};
    var fileDir = './text';
    
    //所有的任务都完成后
    function checkIfComplate(){
      completedTakes++;
      if(completedTakes == takes.length){
        for(var index in wordCounts){
          console.log(index + ': '+wordCounts[index]);
        }
      }
    }
    
    //计算文件中出现的单词数
    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]();
      }
    });
    
    

    水平一般,能力有限。随手记忆~~~~

    你可能感兴趣的:(Nodejs编程基础)