node.js

1.node是什么?

  Node 是一个让 JavaScript 运行在服务端的开发平台, 发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行得更好。 Node用于方便地搭建响应速度快、易于扩展的网络应用。Node 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。

 1) 什么是 V8?

  V8 JavaScript 引擎是 Google 用于其 Chrome 浏览器的底层 JavaScript 引擎。实际上,JavaScript 引擎负责解释并执行代码。Google 使用 V8 创建了一个用 C++ 编写的超快解释器,该解释器拥有另一个独特特征;您可以下载该引擎并将其嵌入任何应用程序。V8 JavaScript 引擎并不仅限于在一个浏览器中运行。因此,Node 实际上会使用 Google 编写的 V8 JavaScript 引擎,并将其重建为可在服务器上使用。

 2) 什么是i/o?
  i/o ( input,output)  就是服务器的一个读写操作比方说声音输入,听歌,网上传递的字符串

 3) 什么是并发?
  一段时间内有多个程序在运行到运行完毕之间

 4) 什么是进程?
  一个软件运行过程中至少要有一个进程对应

 5) 什么是线程?

  线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
  多线程与单线程的效率问题:线程本身由于创建和切换的开销,采用多线程不会提高程序的执行速度,反而会降低速度,但是对于频繁IO操作的程序,多线程可以有效的并发.

 6) 同步和异步有什么区别?  

  同步会阻塞: 循环 script加载src
  异步不会阻塞代码:  定时器,link加载css,img加载src.

 7) 什么是异步的IO.  

  要有数据的交互 异步的IO 读文件
  没有数据的交互 异步的非IO setTimeout setInterval

2.node的解析:
  对象分为两类:
    1) 宿主对象:比如 window history
    2) 内置对象:比如math date regexp array string 
   因为是直接用v8引擎去解析,宿主对象不能解析,没有window对象,此时在node.js中用global表示全局变量,等同于var a.
 
3.常用方法:
 
  1) 断言
var flag = 123;    //假定条件
// 此处省略一万行

// 不能确定flag的值是否还为123,断言判断
console.assert(flag == 1234,'flag的值根本不等于123');
 
  2) 计算时间
console.time('test');
for(var i = 0;i < 100000000;i++){
}
console.timeEnd('test');

  

  3) 路径

console.log(__dirname);   //当前文件所在的路径
console.log(__filename);   //当前文件的全部路径

 

4.node.js中的内置模块

  在node中,有一些内置的模块(包),通过require函数引入 

 内置模块:

  1. fs 文件系统;
  2. http 创建服务;
  3. path 路径;
  4. querystring 参数模块;
  5. url 地址栏;
  6. 自定义模块;
1.fs文件系统的模块:
  1)
读取文件
// fs 文件系统的模块
var fs = require("fs");  
// console.log(fs);

// 异步读取文件
fs.readFile('./08.txt','utf8',function(err,data){   //如果编码格式不写,输出的就是一串buffer码
    // console.log(err);   //这是错误,但是没有抛出
    if(err){
        throw err;   //把错误抛出来,有错误可以阻止代码继续往后面走
    }
    console.log(data)

})

// 同步
// var data = fs.readFileSync("./08.txt",'utf8')   //同步读完就是函数的返回值
// console.log(data);

 

  2)判断文件是否存在

 //判断文件是否存在
fs.access('./08.txt',function(err){  
    if(err){
        throw err;
    }
    // 如果没有抛出错误,文件存在
    fs.readFile('./08.txt','utf8',function(err,data){
        if(err) throw err;

        console.log(data);
    })
})


fs.access("./abc",function(err){    //可以判断文件夹
    if(err){
        throw err;
    }
    console.log('hello')
})

   

  3)写文件

异步写文件
var obj = {
    "uname" : "admin",
    "upassword" : "admin" 
}
var arr = [];
// su shu 
arr.push(obj);
var obj2 = {
    "uname" : "admin2",
    "upassword" : "admin2" 
}
arr.push(obj2)

var str = JSON.stringify(arr);
fs.writeFile('./data/03.json',str,'utf8',function(err){   //如果写入成功,这个err为null
    // console.log(err);
    if(err){
        throw err;    //如果错误,将错误抛出
    }
    console.log('文件写入成功')


    // 如果文件不存在,会帮你去创建对应的文件,但是不会创建文件夹
})

同步写文件
fs.writeFileSync(file, data[, options])

 

  4)追加文件


异步的追加文件
fs.appendFile(path, data[, options], callback)
fs.appendFile("./data/04.json","hello world","utf8",function(err){
    console.log(err);
    console.log('OK')
})

同步的追加文件
fs.appendFileSync(path, data[, options])

 

  5)创建文件夹

异步的创建文件夹
fs.mkdir("./data02",function(err){
    console.log(err);   //node会报错,但是错误都不会抛出,不会影响后续代码的执行
    console.log('OK');
})

同步的创建文件夹
fs.mkdirSync(path[, options])

 

  7)读文件夹

异步读文件夹
fs.readdir(path[, options], callback)
fs.readdir("./data",function(err,data){
    console.log(err);
    console.log(data);   //里面的文件以数组的形式表示出来,进行判断,判断是否是文件夹
    // 如果是文件夹,继续读文件夹,如果是文件,直接读文件,然后展示
})

同步的读文件夹
fs.readdirSync(path[, options])

 

  8)文件夹是否存在

异步判断文件或者文件夹是否存在
fs.access(path[, mode], callback)   能否判断文件夹是否存在
fs.access("./data",function(err){   //这个方法是可以判断文件和文件夹是否存在
    console.log(err);
    console.log('OK');
})

同步判断文件或者文件夹是否存在
fs.accessSync(path[, mode])

 

  9) 文件信息

fs.stat("./data",function(err,stats){
    console.log(err);
    // console.log(stats.isDirectory());
  
//    获取文件的大小;
 if(stats.isDirectory()){
  console.log(
'是文件夹')
 }
else{
  console.log(
'是文件')
 }
    console.log(stats.size);
//    获取文件最后一次访问的时间;
    console.log(stats.atime.toLocaleString());
//    文件创建的时间;
    console.log(stats.birthtime.toLocaleString());
//    文件最后一次修改时间;
    console.log(stats.mtime.toLocaleString());
//    状态发生变化的时间;
    console.log(stats.ctime.toLocaleString())
//判断是否是目录;是返回true;不是返回false;
    console.log(stats.isFile())

    console.log(stats.isDirectory()) })
 

})

  

  10)文件流

  想象一下,如果把文件读取比作向一个池子里抽水,同步会阻塞程序,异步会等待结果,如果这个池子特别大怎么办?有三峡水库那么大怎么办?你要等到多久才能喝到抽的水?因此便会有了文件流,文件流就好比你一边抽一边取,不用等池子满了再用一样方便。

// 文件流   适用于比较大内容

var fs = require("fs");

// 读文件的流
var rs = fs.createReadStream("./../0225-3node文件系统-1.mp4");
// 写文件的流
var ws = fs.createWriteStream("./video.mp4");

var stats = fs.statSync("./../0225-3node文件系统-1.mp4");

// console.log(stats);
var size = stats.size;

// 通过buffer进行传输
var data = 0;
rs.on("data",function(chunk){
    data = data + chunk.length;
    console.log('传输的进度' + (data/size) * 100 + "%");

    ws.write(chunk);
})
rs.on("end",function(){
    console.log('文件读写完成');
    ws.end();
})


// buffer 就是一个对象,有点像数组


var buf = new Buffer(5); //每一个存的值是16进制的
buf[0] = 0x68;
buf[1] = 0x65;
buf[2] = 0x6c;
buf[3] = 0x6c;
buf[4] = 0x6f;

 

 2.http的模块:

 

// 引入http的模块
var http = require("http");

// 创建一个服务
var count = 0;
http.createServer(function(request,response){
    count ++;
    console.log('hello world');
    response.end(count.toString())
}).listen(3000)

 

3. path模块:
  1)获取所在路径(.dirname)
var path = require('path');
var filepath = '/tmp/demo/js/test.js';
 

console.log( path.dirname(filepath) )
// 输出:/tmp/demo/js

  2)获取文件名:(basename)

var path = require('path');

console.log( path.basename('/tmp/demo/js/test.js') );
// 输出:test.js

//如果只想获取文件名,单不包括文件扩展呢?可以用上第二个参数。
console.log( path.basename('/tmp/demo/js/test.js', '.js') );
// 输出:test 

//如果没有文件,获取路径的最后一位
console.log( path.basename('/tmp/demo/js/test/') );
// 输出:test
 

console.log( path.basename('/tmp/demo/js/test') );
// 输出:test

  3) 获取文件扩展名

var path = require('path');
var filepath = '/tmp/demo/js/test.js';
 

console.log( path.extname(filepath) );
// 输出:.js

 

 

5.node服务器

 基本创建步骤:
var http = require("http");   //引入http的模块,用来提供服务
var fs = require("fs");

var server = http.createServer();    //创建一个服务器


//server监听request事件,callback
server.on('request',function(request,response){
    response.writeHead(200,{"Content-Type" : "text/html;charset=utf8"});    // 注意:图片,script,css,文本,html都要与之对应  
     
    // // 输出对应的中文的时候,要有对应的格式和对应的编码

    // response.write("<h1>你好</h1>");

    // response.end("<h2>hello world</h2>");   //结束,结束必须有,不然表示这个请求和响应没有完成

//接口设置
    if(request.url == "/login.html" && request.method == "GET"){
        // response.end("这个是登录界面")
        fs.readFile("./login.html",'utf8',function(err,data){
            response.end(data);
        })

    }else if(request.url == "/register" && request.method == "GET"){
        response.end("这个是注册界面")

    }
    else if(request.url == "/login" && request.method == "POST"){
        response.end("登录成功")
    }

    else {
        response.end("404");
    }


});


// 服务搭建完成,监听端口
server.listen(8888);    //ctrl+c   停止
console.log('服务运行在localhost:8888')

 

 demo:(注册/登录/首页--实现增删改查)
  1.接口文档

  2.服务器部分:

var http =  require("http");
var fs = require("fs");
var querystring = require("querystring");
var url = require("url");
var path = require("path");

var server = http.createServer();

server.on("request",function(req,res){
    var urlObj = url.parse(req.url,true);    //地址栏格式化成对象
    var pathname = urlObj.pathname;            //pathname:当前页面的相对路径
    var query = urlObj.query;    
    console.log(pathname);                    //获取到地址栏的参数    
    
    //静态伺服
    if(pathname == "/formlogin.html" && req.method == "GET"){
        fs.readFile("./formlogin.html","utf8",function(err,data){
            // console.log(err);
            res.end(data);
        })
    }
    else if(pathname == "/register.html" && req.method == "GET"){
        fs.readFile("./register.html","utf8",function(err,data){
            // console.log(err);
            res.end(data);
        })
    }
    else if(pathname == "/shouye.html" && req.method == "GET"){
        fs.readFile("./shouye.html",function(err,data){
            // console.log(err);
            res.end(data);
        })
    }
    //js
    else if(pathname == "/js/formlogin.js" && req.method == "GET"){
        fs.readFile("./js/formlogin.js","utf8",function(err,data){
            // console.log(err);
            res.end(data);
        })
    }
    else if(pathname == "/js/register.js" && req.method == "GET"){
        fs.readFile("./js/register.js","utf8",function(err,data){
            res.end(data);
        })
    }else if(pathname == "/js/shouye.js" && req.method == "GET"){
        fs.readFile("./js/shouye.js","utf8",function(err,data){
            res.end(data);
        })
    }
    //css
    else if(pathname == "/css/formlogin.css" && req.method == "GET"){
        fs.readFile("./css/formlogin.css","utf8",function(err,data){
            res.end(data);
        })
    }
    else if(pathname == "/css/shouye.css" && req.method == "GET"){
        fs.readFile("./css/shouye.css","utf8",function(err,data){
            res.end(data);
        })
    }

    //注册失焦验证
    else if( pathname == "/register_validation" && req.method == "GET"){
            fs.readFile("./data/03.json","utf8",function(err,datas){
                var data = JSON.parse(datas);
                // console.log(data)
                var flag = true;
                //遍历数组,有相同名字的返回false,输出0;没有相同名字的,输出1;
                for(var i = 0; i < data.length; i++){
                    // console.log(query.uname);
                    // console.log(data[i].uname);
                     if(data[i].uname == query.uname){
                        // res.end("0");   //用户名已存在
                        flag = false;
                        break;
                    }
                }    
                if(flag) {
                    res.end("1");   //用户名可以使用
                }else {
                    res.end("0");   //用户名
                }                
                    
            })
    }
    //登录验证
    else if(pathname == "/login" && req.method == "POST"){
        // console.log('1111')
        var data ="";
        req.on("data",function(chunk){
            data += chunk;
        })
        req.on('end',function(){
            var dataobj = querystring.parse(data);
            // console.log(dataobj);
            fs.readFile("./data/03.json","utf8",function(err,data){
                data_login = JSON.parse(data);
                // console.log(data_login);
                // console.log(dataobj.uname);
                // console.log(dataobj.upassword);
                for(var i = 0; i < data_login.length; i++){
                    if(data_login[i].uname == dataobj.uname){
                        if(data_login[i].upassword == dataobj.upassword){
                             res.end("1");   //登录成功
                        }else {
                                res.end("2");   //密码错误
                        }    
                    }
                }
                res.end("0");   //参数错误
            });    
        });                
    }    
    
    //注册按钮
    else if(pathname == "/register" && req.method == "POST"){
        var data ="";
        req.on("data",function(chunk){
            data += chunk;
        })
        console.log("1")
        req.on('end',function(){
            var data_qt = querystring.parse(data);        //用户输入的数据转化为对象的形式
            console.log(data_qt);
            fs.readFile("./data/03.json","utf8",function(err,data){
                // console.log(err);
                // console.log(data);
                
                if(data_qt.uname && data_qt.upassword){
                    var data_ht = JSON.parse(data);    
                    console.log(data_ht);        //后台数据字符串转化为对象的形式
                    data_ht.push(data_qt);
                    var data_ht_str = JSON.stringify(data_ht)
                     fs.writeFile("./data/03.json",data_ht_str,"utf8",function(){
                         res.end("1")        //注册成功
                     });
                    
                }else {
                    res.end("0");    //参数错误
                }
            });    
        });                
    }    

    //获取主页数据
    else if( pathname == "/index_getdata" && req.method == "GET" ){
        fs.access("./data/"+query.uname+".json",function(err){
            if(err){
                fs.writeFile("./data/"+query.uname+".json","[]",function(err){
                    fs.readFile("./data/"+query.uname+".json","utf8",function(err,data){
                        var datas = '{"margin":"ok","data":'+data+'}';
                        // var bm =JSON.parse(datas); 
                        // console.log(bm)
                        res.end(datas);
                    })
                })
            }else {
                fs.readFile("./data/"+query.uname+".json","utf8",function(err,data){
                            var datas = '{"margin":"ok","data":'+data+'}'; 
                        // var bm = JSON.parse(datas); 
                        // console.log(bm)
                        res.end(datas);
                })
            }
        })        
    }


    //增加
    else if(pathname == "/add_data" && req.method == "POST"){

        var data ="";
        req.on("data",function(chunk){                    //监听前台数据的变化
            data += chunk;    
            console.log(data);                        
        })
                                    //字符串
        req.on('end',function(){
            var data_qt = querystring.parse(data);        //用户输入的数据转化为对象的形式
            console.log(data_qt);
            fs.readFile("./data/"+data_qt.uname+".json","utf8",function(err,datas){
                console.log(err);
                // console.log(data);
                var data_ht = JSON.parse(datas);        //后台数据字符串转化为对象的形式
                console.log(data_ht);

                if(data_ht.length == 0){
                    data = {
                       uname : data_qt.uname,
                       pid:0,
                       name:data_qt.name,
                       sex:data_qt.sex,
                       age:data_qt.age,
                       mail:data_qt.mail,
                       phone: data_qt.phone
                    }    
                    data_ht.push(data);
                    var data_ht_str = JSON.stringify(data_ht)
                    fs.writeFile("./data/"+data_qt.uname+".json",data_ht_str,"utf8",function(){
                        res.end("1")        //注册成功
                    });
                }else {
                    data = {
                       uname : data_qt.uname,
                       pid:data_ht[data_ht.length-1].pid+1,
                       name:data_qt.name,
                       sex:data_qt.sex,
                       age:data_qt.age,
                       mail:data_qt.mail,
                       phone: data_qt.phone
                    }
                    data_ht.push(data);
                    var data_ht_str = JSON.stringify(data_ht)
                    fs.writeFile("./data/"+data_qt.uname+".json",data_ht_str,"utf8",function(){
                        res.end("1")        //注册成功
                    });
                }    
                
            });    
        });                
    }    

    //删除按钮
    else if( pathname == "/remove_data" && req.method == "GET" ){
        fs.readFile("./data/"+query.uname+".json","utf8",function(err,data){
            var data = JSON.parse(data);
            var uname = query.uname;
            console.log(data);
            for (var i = 0; i < data.length; i++) {
                if (data[i].pid == query.pid) {
                    // data.splice(i,1);
                    console.log(i)
                    break;
                }
            }
                // console.log(i)
                data.splice(i,1);
                // console.log(data);
                var data_str = JSON.stringify(data);
                // console.log(data_str);
                fs.writeFile('./data/' + uname + ".json",data_str,function(err){
                    res.end("1");
                })
                // console.log(data);
        })
            
    }
    //修改
    else if(pathname == "/revise_data" && req.method == "POST"){
        var data_qt = "";
        req.on("data",function(chunk){
            data_qt += chunk;
        })
        // console.log('1');
        req.on('end',function(err){
            // console.log("2");
              var data_qt_obj = querystring.parse(data_qt);    //用户输入的数据转化为对象的形式
                 // console.log(data_qt_obj)
     //          var uname = data_qt_obj.uname;
     //          var pid = data_qt_obj.pid;
              fs.readFile('./data/' + data_qt_obj.uname + ".json",'utf8',function(err,data){
                  var data_ht_obj = JSON.parse(data);
                  // console.log(data_ht_obj);
                  for(var i = 0;i < data_ht_obj.length;i++){
                      if(data_ht_obj[i].pid == data_qt_obj.pid){
                          break;
                      }
                  }
                  if(data_qt_obj.name){
                      data_ht_obj[i].name = data_qt_obj.name
                  }
                  if(data_qt_obj.sex){
                      data_ht_obj[i].sex = data_qt_obj.sex
                  }
                  if(data_qt_obj.age){
                      data_ht_obj[i].age = data_qt_obj.age
                  }
                  if(data_qt_obj.mail){
                      data_ht_obj[i].mail = data_qt_obj.mail
                  }
                  if(data_qt_obj.phone){
                      data_ht_obj[i].phone = data_qt_obj.phone
                  }
                  var str = JSON.stringify(data_ht_obj);
                  fs.writeFile('./data/' + data_qt_obj.uname + ".json",str,function(err){
                    res.end("1");
                })
              })
          })
    }



})

server.listen(3535);
console.log("server running in localhost:3535");
console.log("\n")

 

posted on 2019-03-04 20:25  1234wu  阅读(303)  评论(0编辑  收藏  举报

导航