一、创建http服务器
node.js的web程序不用放入web容器中运行,可以自己创建一个http服务器运行程序。需要使用http核心模块。
1 //创建一个http服务器
2 const http=require('http');
3 //创建一个http服务器
4 const server=http.createServer((req,res)=>{
5 //设置响应头
6 res.writeHead(200, {'Content-Type': 'text/html;charset=utf8'});
7 //通知服务器,所有响应头和响应主体都已被发送
8 res.end("hello world");
9 });
10 server.listen('8080',"127.0.0.1",(err)=>{
11 if(err)
12 throw err;
13 console.log("服务器启动成功");
14 })
可以在浏览器通过http://localhost:8080访问服务器。
二、访问服务器上的静态页面
1 //创建一个http服务器
2 const http = require('http');
3 const fs = require('fs');
4 //创建一个http服务器
5 const server = http.createServer((req, res) => {
6 if (req.url == "/yuan") {
7 //访问页面yuan.html
8 fs.readFile('./yuan.html', "utf8", (err, data) => {
9 if (err)
10 throw err;
11 //设置响应头
12 res.writeHead(200, { 'Content-Type': 'text/html;charset=utf8'});
13 //通知服务器,所有响应头和响应主体都已被发送
14 res.end(data);
15 });
16 } else if (req.url == '/fang') {
17 //访问页面fang.html
18 fs.readFile('./fang.html', "utf8", (err, data) => {
19 if (err)
20 throw err;
21 //设置响应头
22 res.writeHead(200, { 'Content-Type': 'text/html', 'charset': "utf8" });
23 //通知服务器,所有响应头和响应主体都已被发送
24 res.end(data);
25 });
26 }
27 else if (req.url == "/tupian") {
28 //为图片配置路由
29 fs.readFile('./node.png', (err, data) => {
30 if (err)
31 throw err;
32 //设置响应头
33 //通知服务器,所有响应头和响应主体都已被发送
34 res.end(data);
35 });
36 }
37 else {
38 //加载含有图片的页面要配置多个路由
39 fs.readFile('./tupian.html', (err, data) => {
40 if (err)
41 throw err;
42 //设置响应头
43 //通知服务器,所有响应头和响应主体都已被发送
44 res.end(data);
45 });
46 }
47 });
48 server.listen('8080', "127.0.0.1", (err) => {
49 if (err)
50 throw err;
51 console.log("服务器启动成功");
52 })
设置四个简单的路由,获取服务器上的静态页面。
三、闭包和链式调用
使用下面的代码读取./album文件夹下的所有文件,把其中的文件夹放入dir数组中。然后遍历dir数组。./album下的文件如下:
1 const fs = require('fs');
2 var dir=[];
3 fs.readdir('./album',(err,files)=>{
4 for(var i=0;i<files.length;i++){
5 var thefile=files[i];
6 fs.stat(`./album/${thefile}`,(err,state)=>{
7 if(state.isDirectory())
8 dir.push(thefile);
9 console.log(dir);
10 });
11 }
12 })
控制台打印的结果如下:
分析: fs.readdir()的回调函数中定义了变量thefile,回调函数在调用的时候会把变量thefile绑定到相关的对象上。回调函数中又定义了回调函数,所以嵌套的回调函数会把这个对象添加到自己的作用域上。但是fs.readdir()调用时循环会改变thefile的值,所以回调函数的作用域连上的thedfile指向最后一个文件名。
fs.stat(`./album/${thefile}`,callback)中我们传入的实参是对应的每一个的文件名。
解决方法1:利用闭包让thefile变量不共享。
1 const fs = require('fs');
2 var dir=[];
3 fs.readdir('./album',(err,files)=>{
4 for(var i=0;i<files.length;i++){
5 var thefile=files[i];
6 (function (f){
7 fs.stat(`./album/${f}`,(err,state)=>{
8 if(state.isDirectory())
9 dir.push(f);
10 console.log(dir);
11 });
12 }(thefile))
13 }
14 })
解决方法2:每次只让事件队列中有一个fs.stat()函数在执行。
1 const fs = require('fs');
2 var dir=[];
3 fs.readdir('./album',(err,files)=>{
4 (function itera(f){
5 //结束递归
6 if(f===files.length){
7 console.log(dir);
8 return;
9 }
10 fs.stat(`./album/${files[f]}`,(err,state)=>{
11 if(state.isDirectory())
12 dir.push(files[f]);
13 console.l
14 og(`./album/${files[f]}`);
15 itera(++f);
16 });
17 }(0))
18 })
五、自己实现静态服务
1 //用node提供静态服务
2 const http = require('http');
3 const fs = require('fs');
4 const url = require('url');
5 const path = require('path');
6 const server = http.createServer((req, res) => {
7 //获取要访问的文件路径
8 let requrl = url.parse(req.url).pathname;
9 //拼合成绝对路径
10 let dirpath = path.join(__dirname, 'static', requrl);
11 //读取当前路径下的文件
12 fs.readFile(dirpath, (err, data) => {
13 //当前文件不存在
14 if (err) {
15 let p404 = path.join(__dirname, 'static/404.html');
16 fs.readFile(p404, (err, data) => {
17 if (err)
18 throw err;
19 res.writeHead(404, { 'Content-Type': `text/html;charset=utf8` });
20 res.end(data)
21 });
22 return;
23 }
24 //文件存在
25 //获取文件的后缀名
26 let ext = path.extname(requrl);
27 //异步的方式获取响应头
28 getMime(ext, (mime) => {
29 res.writeHead(200, { 'Content-Type': `${mime};charset=utf8` });
30 res.end(data);
31 });
32 });
33 });
34 server.listen('8080', 'localhost', (err) => {
35 if (err)
36 throw err;
37 console.log("服务器成功启动!");
38 });
39 //根据文件的类型给出对应的mime类型
40 function getMime(extname, callback) {
41 let file = path.join(__dirname, 'mime.json');
42 fs.readFile(file, (err, data) => {
43 if (err)
44 throw err;
45 data = JSON.parse(data);
46 let mime = data[extname] || "text/plain";
47 callback(mime);
48 })
49 }
当服务器启动时,放在static文件下的问价可以被直接访问。
六、post请求和get请求
1 //post请求
2 const http = require('http');
3 const fs = require('fs');
4 const querystring=require('querystring');
5 http.createServer((req, res) => {
//读取服务器上的静态页面
6 if (req.url == '/') {
7 fs.readFile('./form.html', (err, data) => {
8 if (err)
9 throw err;
10 res.writeHead(200, { 'Content-Type': `text/html;charset=utf8` });
11 res.end(data);
12 })
13 }
//接受post请求
14 else if (req.url = "/dopost" && req.method.toLocaleLowerCase() == 'post') {
15 let data = '';
16 req.addListener('data', (chunk) => {
17 data += chunk;
18 });
19 req.addListener('end', () => {
//打印接受的数据
20 console.log(data);
//将数据转换成字符串
21 let dataObj=querystring.parse(data);
22 console.log(dataObj.user);
23 })
24 res.writeHead(200, { 'Content-Type': `text/html;charset=utf8` });
25 res.end('success');
26 }
27 else {
28 res.writeHead(200, { 'Content-Type': `text/html;charset=utf8` });
29 res.end('404');
30 }
31 }).listen('8080', 'localhost');
1 //get请求 2 const http=require('http'); 3 const url=require('url'); 4 //创建一个服务器 5 http.createServer((req,res)=>{ 6 //解析接受到url 7 //输入http://localhost:8080/lijunjie.hml?name=123 8 let urlObj=url.parse(req.url); 9 //输出name=123 10 console.log(urlObj.query); 11 res.end('请求成功'); 12 }).listen(8080,'localhost');
七、ejs模板引擎
首先需要通过npm安装ejs模块。创建index.ejs文件。
1 <!DOCTYPE html>
2 <html lang="en">
3
4 <head>
5 <meta charset="UTF-8">
6 <title>Document</title>
7 </head>
8
9 <body>
10 <p> 我买了一个小米
11 <%=a%>
12 </p>
13 <% for(var i=0;i<news.length;i++){%>
14 <li>
15 <%=news[i]%>
16 </li>
17 <%}%>
18 </body>
bind.js文件
1 //创建一个http服务器
2 const http = require('http');
3 const fs = require('fs');
4 const ejs=require('ejs');
5 //创建一个http服务器
6 const server = http.createServer((req, res) => {
7 //读取模板
8 fs.readFile('./index.ejs', (err, data) => {
9 //接受模板
10 let template = data.toString();
11 //数据
12 let datas = { a: 3, news: ['adsada', 'xiaomi'] };
13 let html=ejs.render(template,datas);
14 res.end(html);
15 })
16
17 });
18 server.listen('8080', "127.0.0.1", (err) => {
19 if (err)
20 throw err;
21 console.log("服务器启动成功");
22 })