欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

node.js

程序员文章站 2024-02-01 21:21:16
1.node是什么? Node 是一个让 JavaScript 运行在服务端的开发平台, 发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行得更好。 Node用于方便地搭建响应速度快 ......

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.接口文档
node.js

  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")