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 引擎,并将其重建为可在服务器上使用。
3) 什么是并发?
一段时间内有多个程序在运行到运行完毕之间
4) 什么是进程?
一个软件运行过程中至少要有一个进程对应
5) 什么是线程?
线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
多线程与单线程的效率问题:线程本身由于创建和切换的开销,采用多线程不会提高程序的执行速度,反而会降低速度,但是对于频繁IO操作的程序,多线程可以有效的并发.
6) 同步和异步有什么区别?
同步会阻塞: 循环 script加载src
异步不会阻塞代码: 定时器,link加载css,img加载src.
7) 什么是异步的IO.
要有数据的交互 异步的IO 读文件
没有数据的交互 异步的非IO setTimeout setInterval
var flag = 123; //假定条件
// 此处省略一万行
// 不能确定flag的值是否还为123,断言判断
console.assert(flag == 1234,'flag的值根本不等于123');
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函数引入
内置模块:
- fs 文件系统;
- http 创建服务;
- path 路径;
- querystring 参数模块;
- url 地址栏;
- 自定义模块;
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)
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')
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")