nodejs
nodeJS
1.安装nodejs
从nodejs官网下载最新版本的node,设置环境变量这样就可以在cmd下直接用命令行操作npm
环境变量:path d:/nodejs
查看本机node及npm版本
2.从官网上直接拷一个小脚本:
新建nodeExample.js
const http = require('http'); const hostname = '127.0.0.1'; const port = 3000; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World\n'); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
可以通过控制台直接运行:
打开浏览器输入http://127.0.0.1:3000/,页面上出现Hello World
如果将Hello World改成Hello NodeJs,刷新浏览器发现页面还是没变,此时要再次在控制台再次运行该js文件,Ctrl+C结束上次活动
函数篇
看一个本地函数nodeExample.js
var http=require('http'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ fun1(response); response.end(); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/'); function fun1(res){ console.log('fun1'); res.write("hello,this is fun1"); }
如果是别的地方引用的函数
新建function2.js
function fun2(res){ console.log('fun2'); res.write('hello,this is fun2'); } module.exports=fun2;
nodeExample.js修改为
var http=require('http'); var otherFun=require("./function2.js"); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ fun1(response); otherFun(response); response.end(); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/'); function fun1(res){ console.log('fun1'); res.write("hello,this is fun1"); }
控制台使用node命令执行nodeExample.js
支持多个函数:
function2.js
module.exports={ fun2:function(res){ console.log('fun2'); res.write('hello,this is fun2'); }, fun3:function(res){ console.log('fun3'); res.write('hello,this is fun3'); } }
nodeExample.js
var http=require('http'); var otherFun=require("./function2.js"); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ otherFun.fun2(response); otherFun.fun3(response); response.end(); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
调用时也可以这样:otherFun['fun3'](response);
也可以这样:
funname='fun3';
otherFun[funname ](response);
调用模块
创建User.js
function User(id,name,age){ this.id=id; this.name=name; this.age=age; this.enter=function(){ console.log(this.name+'进入图书馆'); } } module.exports=User;
nodeExample.js
var http=require('http'); var User=require("./User.js"); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ user=new User(1,"张三",20); user.enter(); response.end(); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
运行,再增加Teacher.js
var User=require('./User'); function Teacher(id,name,age){ User.apply(this,[id,name,age]); this.teach=function(res){ res.write(this.name+"讲课"); } } module.exports=Teacher;
nodeExample.js
var http=require('http'); var Teacher=require("./Teacher"); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ teacher=new Teacher(1,"张三",20); teacher.enter(); teacher.teach(response); response.end(); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/'
路由
var http=require('http'); var url=require('url'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; console.log(pathname); response.end(); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
在浏览器在Url地址后加上login,结果:
如果不想要/,可以通过正则去掉
var http=require('http'); var url=require('url'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; //替换掉前面的/ pathname=pathname.replace(/\//,''); console.log(pathname); response.end(); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
新建route.js
module.exports={ login:function(req,res){ res.write("this is login method!"); }, zhuce:function(req,res){ res.write("This is zhuce method"); } }
nodeExample.js
var http=require('http'); var url=require('url'); var route=require('./route'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; //替换掉前面的/ pathname=pathname.replace(/\//,''); console.log(pathname); route[pathname](request,response); response.end(); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
如果浏览器上输入其他url地址,后台就会报错:
读文件
同步方式读取文件
创建openFile.js
var fs=require('fs'); module.exports={ readFileSync:function(path){ var data=fs.readFileSync(path,'utf-8'); console.log(data); console.log("同步方法执行完毕"); } }
nodeExample.js
var http=require('http'); var openFile=require('./openFile'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ //这里的path是相对于openFile.js路径的 openFile.readFileSync('./login.html'); response.end(); console.log('主程序执行完毕'); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
在跟openFile.js文件相同的路径下创建login.html,该html中只有 登录成功 四个字
在控制台执行命令:
异步方式读取文件
openFile.js修改为:
var fs=require('fs'); module.exports={ readFile:function(path){ fs.readFile(path,function(err,data){ if(err){ console.log(err); }else{ console.log(data.toString()); } }); console.log("异步方式执行完毕"); } }
nodeExample.js
var http=require('http'); var openFile=require('./openFile'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ openFile.readFile('./login.html'); response.end('ok'); console.log('主程序执行完毕'); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
也就是说,程序执行到fs.readFile()这个函数时,这个函数还没有执行完,程序自动往下走,先读出了console.log("异步方式执行完毕");
如果将程序openFile.js改为:
var fs=require('fs'); module.exports={ readFile:function(path,res){ fs.readFile(path,function(err,data){ if(err){ console.log(err); }else{ console.log(data.toString()); res.write(data); } }); console.log("异步方式执行完毕"); } };
nodeExample.js相应的修改函数:openFile.readFile('./login.html',response);
主要的问题是,openFile.readFile('./login.html',response);这个函数还没有执行完,response.end('ok');就已经执行完了
可以用闭包开解决:
nodeExample.js
var http=require('http'); var openFile=require('./openFile'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;chaeset=utf-8'}); if(request.url!="/favicon.ico"){ function recall(data){ response.write(data); response.end('ok'); } openFile.readFile('./login.html',recall); console.log('主程序执行完毕'); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
openFile.js
var fs=require('fs'); module.exports={ readFile:function(path,recall){ fs.readFile(path,function(err,data){ if(err){ console.log(err); }else{ console.log(data.toString()); recall(data); } }); console.log("异步方式执行完毕"); } };
执行过程:执行到openFile.readFile()函数时,开个内存执行该函数,另一个继续往下执行函数之后的程序,先把能执行的给执行,不能立刻执行的继续执行
将之前的路由修改为:
nodeExample.js
var http=require('http'); var url=require('url'); var route=require('./route.js'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; pathname=pathname.replace(/\//,''); route[pathname](request,response); } }).listen(8000); console.log('server running at http://127.0.0.1:8000/');
route.js
var openFile=require('./openFile'); module.exports={ login:function(req,res){ function recall(data){ res.write(data); res.end(); } openFile.readFile('./login.html',recall); } }
openFile.js
var fs=require('fs'); module.exports={ readFile:function(path,recall){ fs.readFile(path,function(err,data){ if(err){ console.log(err); }else{ console.log(data.toString()); recall(data); } }); console.log("异步方式执行完毕"); } };
程序首先得到了pathname,如login,转到login函数,执行openFile.readFile()函数,将login.html读取出来,并将读取的内容通过recall函数写出来
写文件
也有同步跟异步两种方式
新增writeFile.js
var fs=require('fs'); module.exports={ writeFile:function(path,data,recall){ fs.writeFile(path,data,function(err){ if(err){ throw err; } console.log('This file is saved'); recall('write file success'); }); }, writeFileSync:function(path,data){ fs.writeFileSync(path,data); console.log('同步写文件成功'); } }
route.js
var openFile=require('./openFile'); var writeFile=require('./writeFile') module.exports={ login:function(req,res){ function recall(data){ res.write(data); res.end(); } openFile.readFile('./login.html',recall); }, writeFile:function(req,res){ function recall(data){ res.write(data); res.end(); } writeFile.writeFile('./one.txt','我的写入文件',recall) } }
nodeExample.js
var http=require('http'); var url=require('url'); var route=require('./route.js'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'text/html;chaeset=utf-8'}); if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; pathname=pathname.replace(/\//,''); route[pathname](request,response); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
成功之后打开one.txt可以看到 我的写入文件
读取图片
nodeExample.js
var http=require('http'); var openFile=require('./openFile.js'); http.createServer(function(request,response){ response.writeHead(200,{'Content-Type':'image/jpeg'}); if(request.url!="/favicon.ico"){ openFile.readImg('./image.png',response); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
openFile.js
var fs=require('fs'); module.exports={ readImg:function(path,res){ fs.readFile(path,'binary',function(err,file){ if(err){ console.log(err); return; }else{ console.log('输出文件'); res.write(file,'binary'); res.end(); } }) } };
如果加上文字,就会报错,如:
if(request.url!="/favicon.ico"){ response.write('hello world'); openFile.readImg('./image.png',response); }
此时图片就无法显示
再写路由的一个例子,解决这个问题
nodeExample.js
var http=require('http'); var url=require('url'); var route=require('./route.js'); http.createServer(function(request,response){ if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; pathname=pathname.replace(/\//,''); route[pathname](request,response); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/'); route.js var openFile=require('./openFile'); module.exports={ login:function(req,res){ res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); function recall(data){ res.write(data); res.end(); } openFile.readFile('./login.html',recall); }, showImg:function(req,res){ res.writeHead(200,{'Content-Type':'image/jpeg'}); openFile.readImg('./image.png',res); } }
openFile.js
var fs=require('fs'); module.exports={ readFile:function(path,recall){ fs.readFile(path,function(err,data){ if(err){ console.log(err); }else{ console.log(data.toString()); recall(data); } }); console.log("异步方式执行完毕"); }, readImg:function(path,res){ fs.readFile(path,'binary',function(err,file){ if(err){ console.log(err); return; }else{ console.log('输出文件'); res.write(file,'binary'); res.end(); } }) } };
login.html
<html>
<head>
</head>
<body>
登录界面
<img src="./showImg">
</body>
</html>
异常处理
如果请求路径不正确,后台就会报错,对异常进行处理,将上面的例子中的nodeExample.js修改为:
ar http=require('http'); var url=require('url'); var route=require('./route.js'); http.createServer(function(request,response){ if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; pathname=pathname.replace(/\//,''); try{ route[pathname](request,response); console.log('..............'); }catch(err){ console.log('error is:'+err); response.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); response.write(err.toString()); response.end(); } console.log('server finish'); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
从结果可以发现:route[pathname](request,response);执行报错后,console.log('..............');并没有执行
如果请求的url是正确的,但是readFile()方法读取文件的路径是错误的,那么如何处理这种异常呢
nodeExample.js
var http=require('http'); var url=require('url'); var route=require('./route.js'); http.createServer(function(request,response){ if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; pathname=pathname.replace(/\//,''); try{ route[pathname](request,response); console.log('..............'); }catch(err){ console.log('aaaa:'+err); response.writeHead(200,{'Content-Type':'text/html;chaeset=utf-8'}); response.write(err.toString()); response.end(); } console.log('server finish'); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
route.js
var openFile=require('./openFile'); module.exports={ login:function(req,res){ res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); function recall(data){ res.write(data); res.end(); } openFile.readFile('./log.html',recall); } }
openFile.js
var fs=require('fs'); module.exports={ readFile:function(path,recall){ fs.readFile(path,function(err,data){ if(err){ console.log("bbbb:"+err); }else{ console.log(data.toString()); recall(data); } }); console.log("异步方式执行完毕"); } };
浏览器上输入网址:http://127.0.0.1:8000/login,发现该页面一直在加载(主要是没有执行到recall方法,也就没有执行到response.end()方法,所以页面响应一直无法结束),后台如下:
nodejs和java在异常处理方面是不一样的,如果异步时发生异常,是无法在主程序捕获的,上例中异步发生异常是时程序是可以执行到console.log('..............'); 这一步的,所以必须在异步的地方处理异常,将openFile.js修改为:
var fs=require('fs'); module.exports={ readFile:function(path,recall){ fs.readFile(path,function(err,data){ if(err){ console.log("bbbb:"+err); recall('file not exist'); }else{ console.log(data.toString()); recall(data); } }); console.log("异步方式执行完毕"); } };
也就是说,我们要在出现错误的openFile.js里处理异常
我们也可以专门写一个异常类,将异常抛出,增加Exception.js
module.exports={ expfun:function(flag){ if(flag==0){ throw '我是例外'; } return 'success'; } }
nodeExample.js
var http=require('http'); var url=require('url'); var route=require('./route.js'); var exception=require('./exception') http.createServer(function(request,response){ if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; pathname=pathname.replace(/\//,''); try{ data=exception.expfun(10); response.write(data); response.end(); }catch(err){ console.log('aaaa:'+err); response.writeHead(200,{'Content-Type':'text/html;chaeset=utf-8'}); response.write(err.toString()); response.end(); } console.log('server finish'); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
将nodeExample.js中修改为:data=exception.expfun(0);
参数接收
以get方式
nodeExample.js
http=require('http'); var url=require('url'); var route=require('./route.js'); http.createServer(function(request,response){ if(request.url!="/favicon.ico"){ var pathname=url.parse(request.url).pathname; pathname=pathname.replace(/\//,''); try{ route[pathname](request,response); console.log('..............'); }catch(err){ console.log('aaaa:'+err); response.writeHead(200,{'Content-Type':'text/html;chaeset=utf-8'}); response.write(err.toString()); response.end(); } console.log('server finish'); } }).listen(8000); console.log('serer running at http://127.0.0.1:8000/');
修改login.html
<html> <head> </head> <body> 登录界面 <img src="./showImg"> <form action="./login" method="get"> <table align="center"> <tr> <td>email:</td> <td><input type="text" name="email"/></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="pwd"/></td> </tr> <tr> <td align="center"><input type="submit" value="登录" /></td> </tr> </form> </body> </html>
route.js
var openFile=require('./openFile'); var url=require('url'); function getRecall(req,res){ res.writeHead(200,{'Content-Type':'text/html;chaeset=utf-8'}); function recall(data){ res.write(data); res.end(); } return recall; } module.exports={ login:function(req,res){ //get方式接收参数 var rdata=url.parse(req.url,true).query; console.log(rdata); if(rdata['email']!=undefined){ console.log(rdata['email']); console.log(rdata['pwd']); } recall=getRecall(req,res); openFile.readFile('./login.html',recall); }, showImg:function(req,res){ res.writeHead(200,{'Content-Type':'image/jpeg'}); openFile.readImg('./image.png',res); } }
openFile.js
var fs=require('fs'); module.exports={ readFile:function(path,recall){ fs.readFile(path,function(err,data){ if(err){ console.log("bbbb:"+err); recall('file not exist'); }else{ console.log(data.toString()); recall(data); } }); console.log("异步方式执行完毕"); }, readImg:function(path,res){ fs.readFile(path,'binary',function(err,file){ if(err){ console.log(err); return; }else{ console.log('输出文件'); res.write(file,'binary'); res.end(); } }) } };
后台也可以捕获到,这里的rdata就是一个对象
以post方式
将route.js修改为:
var openFile=require('./openFile'); var url=require('url'); var querystring=require('querystring');//post需导入 function getRecall(req,res){ res.writeHead(200,{'Content-Type':'text/html;chaeset=utf-8'}); function recall(data){ res.write(data); res.end(); } return recall; } module.exports={ login:function(req,res){ //post方式接收参数 //定义一个post变量,用于暂存请求体的信息 var post=''; //通过req的data事件监听函数,每当接收到请求体的数据,就存到post变量中 req.on('data',function(chunk){ post+=chunk; }); //在end事件触发后,通过querystring.parse将poset解析为真正的post格式,然后向客户端返回 req.on('end',function(){ post=querystring.parse(post); console.log('接收参数:'+post['email']+'\n'); console.log('接收参数:'+post['pwd']+'\n'); }) recall=getRecall(req,res); openFile.readFile('./login.html',recall); }, showImg:function(req,res){ res.writeHead(200,{'Content-Type':'image/jpeg'}); openFile.readImg('./image.png',res); } }
将login.html的提交方式改为post
输入email和密码提交之后:
post方式是异步的,因为要拿到所有的请求信息后才能进行处理