node菜鸟入门笔记

node是一个让js运行在服务器端的开发平台,使得javascript的触角衍生到了服务器端,与python、ruby、php平起平坐。

但node有些不同:

1.其并非一门独立语言,与php、jsp的“既是语言,也是平台”不同,node.js的使用javascript进行编程,运行于javascript引擎之上。
2.与php,jsp相比,node跳过了apache、nginx、iis等http服务器,他自己不需要建设在任何服务器软件之上.
    node的许多设计理念与经典架构(lamp)有着很大的不同,可以提供强大的伸缩能力

Node三个极限特点:

1.单线程
    node只有一个线程,所有的用户都是用这一根线程完成服务.
2.非阻塞I/O
    在阻塞模式下,一个线程为所有用户提供服务
3.事件驱动
    聪明的node面对i/o的时候,并不会傻傻地等待当个需要处理i/o的线程任务完毕之后在处理下一个,它会将需要处理i/o的任务存放到内部的一种栈中,先完成便于完成的服务,再回头依次解决各种任务.

Node.js底层是C++(v8同样是使用C++)编写.对于其底层代码中,有接近半数都是用是事件队列、回调函数队列的构建。用事件驱动来完成服务器的任务调度。

node适合做什么开发?

善于I/O,不善于计算.因为node最擅长的就是任务调度,如果你的业务有很多的cpu计算,实际上也相当于这个计算阻塞了这个单线程,就不适合Node开发.
当应用程序需要处理大量的并发I/O,而向客户端发出相应之前,应用程序内部并不需要进行非常复杂的处理的时候,node非常适合.node也同样非常适合与websocket配合,开发长连接的实时交互应用程序

helloworld

注意:

  1. node是服务器程序,书写的js语句,都将运行在服务器之上。 返回给客户的,都是已经处理好的纯html。无法查看网页源代码
  2. node可以直接运行js文件(直接将js文件拖入浏览器中是无法识别的)
  3. node没有web容器! 无法通过node指令 运行html文件。但,我们可以使用fs模块,通过它的readfile()方法,读取html文件,并在回调函数中将其渲染

由于该方法属于http模块,使用前需要引入http模块(var http= require(“http”) )
本质:

  http.createServer([requestListener])

接收参数:
requestListener 请求处理函数,自动添加到 request 事件,函数传递两个参数:
      req 请求对象,想知道req有哪些属性,可以查看 “http.request 属性整合”。
      res 响应对象 ,收到请求后要做出的响应。想知道res有哪些属性,可以查看 “http.response属性整合”。

	//引包  : 引用自己的某个特殊功能
	var http = require("http");
	//创建服务器,参数是一个回调函数,表示如果有请求进来,需要完成什么
	var server = http.createServer(function(req,res){
		//req  表示请求,request;res表示响应,response
		//设置HTTP头部,状态码为200,文件类型是html,字符集是utf8
		res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
		// res.end("这是我的第一个node页面");
		//每一个回调函数,都需要一个end函数
		//否则浏览器会持续等待浏览器发送end中的内容,直到访问超时,所以即便end中给一个空,也不要不给.
		res.end("我买了一部华为P"+(8+10+12)+"pro");
	});
	
	//运行服务器   监听3000端口号	
	server.listen(3000,"127.0.0.1")
	
	//设置完毕之后,使用 node +  "文件所在目录" 打开
上述代码中也可以通过:res.setHeader("Content-Type","text/html;charset=utf-8")直接设置编码格式
就不需要在writeHeader中重复编写了

node的路由:
说起来node的路由很有意(麻)思(烦)。在请求地址根后斜杠后添加上一串字符,node会截取该字符,并用于if的判断上,如果匹配成功,则显示某个页面,否则显示其余页面,或提示访问者无此页面。


	var http = require("http");
	//fs包用于文件读取
	var fs = require("fs");
	var server = http.createServer(function(req,res){
		//使用fs读取上层目录的index文件
		
		if (req.url == "/haha") {
		        //当截取的字符串匹配‘haha’成功时
		        //fs会读取circle.html
			fs.readFile("./circle.html",function(err,data){
			    //**注意 :  此处千万不要写成了  data.writeHead(......)**
			    //调用writehead方法的对象还是 http.createServer实例的res对象
				res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
				//data的显示,是通过res.end(对象名)  
				res.end(data)
			})
		}else if(req.url == "/index"){
		//url等于index时,显示index页面
			fs.readFile("../index.html",function(err,data){
				res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
				res.end(data)
			})		
		}else{
		//并未匹配成功  ,显示  "没有此页面"
			res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
			res.end("没有这个页面")
		}
	});
	//监听地址与端口
	server.listen(3000,"127.0.0.1")

当需要显示单个图片可以写成

	if(req.url == "/0.jpg"){
		fs.readFile("./0.jpg",function(err,data){
		//contenr需要改变
			res.writeHead(200,{"Content-type":"image/jpg"});
			res.end(data)
		})
	}

http模块

在前几个例子中,已经介绍了http模块的部分特点.下面再添加几个视频中提及到的知识点:

res.writeHead()
//该格式可以识别HTML结构,编码格式是UTF-8 >
res.writeHead(200,{‘Content-Type’:‘text/html;charset=UTF8’});
//该格式不可以识别HTML结构,显示的是纯文本
res.writeHead(200,{‘Content-Type’:‘text/plain;charset=UTF8’});
//该格式识别图片
res.writeHead(200,{‘Content-Type’:‘image/jpg;charset=UTF8’});
//该格式识别样式
res.writeHead(200,{‘Content-Type’:‘text/css;charset=UFT8’});
------我是分割线---------------
res.write();
用来输出相应的返回数据
res.end()
res.end()需要时最后一个执行的方法,否则会报错,且参数希望是一个字符串或者缓存区内容,不可以执行如:
res.end(2+3+4) //报错
希望写成:
res.end((2+3+4).toString())

var http = require('http');
var server = http.createServer(function (req,res) {
	if(req.url == "/"){
		$msg = "this is index"
	}else if(req.url == "/login"){
		$msg = "this is login"
	}else{
		$msg = "404"
	}
	console.log("服务器接收到了请求"+req.url)
    /*因为实际开发中,我们需要返回对应的中文以及对应的的文本格式

     * 所以我们需要设置对应的响应头,响应头决定了对应的返回数据的格式以及编码格式

     * writeHead:这个方法有两个参数,第一个参数表示对应的编码的状态值,第二个表示对应的设置*/

    res.writeHead(200,{'Content-Type':'text/html;charset=UTF8'});
	res.write($msg);
    res.end('<h1>我是h1标签</h1>');
});
server.listen(3000,'127.0.0.1');

模块的三种分类

  1. 内置/核心模块:http服务、fs文件操作、url路径、path路径处理、os操作系统
  2. 第三方模块
  3. 自定义模块

自定义模块需要遵守的约定—CommonJs

  1. 一个文件就是一个模块
  2. 通过exports和modul.exports来到出模块中的成员(需要生命模块中哪些功能可以使用)
  3. 模块需要通过require加载

语法

###步骤1:导出成员(声明模块/文件中哪些方法可以被外部调用)
//写法1
exports.属性/方法名 = 功能
//写法2
module.exports.属性/方法名 = 变量名;
###步骤2:外部引入使用
var 对象 = require("路径及文件名");
对象.属性或方法名;

接下来我们写个demo:

//b.js 在b.js中定义模块
	//step1 :定义
	var add = () =>{ console.log("add: 此方法可以执行增加操作")}
	var del = () =>{ console.log("del: 此方法可以执行删除操作")}
	var edit = () =>{ console.log("edit: 此方法可以执行编辑操作")}
	var select = () =>{ console.log("select: 此方法可以执行查询操作")}
	
	//step2 :导出 (语法: exports/module.exports.成员名/方法名 = 值)
	exports.add = add;
	module.exports.del = del;
	exports.edit = edit;
	module.exports.select = select;
//a.js  a.js负责引入
let moduleb = require("/b");//注意,这里的后缀不需要写上
console.log(module);
//以下是打印出来的东西
//C:\Users\LYn\Documents\HBuilderProjects\node学习\js>node a.js
//{ add: [Function: add],
//  del: [Function: del],
//  edit: [Function: edit],
//  select: [Function: select] }

moduleb.add();
//打印出(实际就是b.js中箭头函数的函数体):  此方法可以执行增加操作

OS模块学习:

	let myos = require("os");
	console.log('hello'   +myos.EOL+ 'itcast');
	console.log("主机名"+myos.hostname());
	console.log("操作系统名"+myos.type());
	console.log("操作系统平台" +myos.platform);
	console.log("内存总量" +myos.totalmem+"字节");
	console.log("空闲内存" +myos.freemem() +"字节");
	
	//打印出
	hello
	itcast		//此处hello 与 itcast换行的原因是 有myos.EOL 这是个换行
	主机名DESKTOP-90M26FL
	操作系统名Windows_NT
	操作系统平台win32
	内存总量8484425728字节
	空闲内存4014014464字节

path模块学习

dirname  表示回退一层目录
basename  表示到最深层目录(或文件)
	let mypath = require("path");
	var testpath = "c:/app/view/index.html"
	console.log(mypath.basename(testpath));		//输出index.html
	testpath = mypath.dirname(testpath);
	console.log(testpath);						//输出 c:/app/view
	testpath = mypath.dirname(testpath)
	console.log(testpath);						//输出c:/app

url模块学习

	let myurl = require("url");
	var data = 'http://itcast.cn?name=张三&age=18';
	console.log(data);
	console.log(myurl.parse(data));
	console.log(myurl.parse(data,true));		//添加上true参数可以将 query属性的值转变为对象
	console.log(myurl.parse(data).search);		//属性同样支持点号运算符,这是个对象

fs模块读写操作

	var fs = reuqire("fs");		//引入模块
	fs.writeFile("./a.txt","你好,未来",(err)=>{
		if(err){console.log(err);return;}
		console.log("success");
	})
fs的 writeFile方法的三个参数,分别是:对应的文件、需要输入的文字、回调函数。
//写法一
	var fs = reuqire("fs");		//引入模块
	fs.readFile("./a.txt",(err,data)=>{
		if(err){console.log(err);return;}
		console.log(data);
		//这里的内容我们无法识别 是一个buffer对象(缓冲区) 
		//通过Buffer对象  Buffer.toString()转换为字符显示
		console.log(data.toString());		//成功打印
	})
//写法二  咋子readfile函数中增加一个字符参数
fs.readFile("./a.txt","utf8",(err,data)=>{
		if(err){console.log(err);return;}
		console.log(data);
	})
fs的 readFile方法的回调函数中第一个参数是err,第二个是获取的数据

Demo 我们接下来会使用node搭建一个小的服务器

目录解构

目录解构
处理静态资源的主要代码(js):
html页面只是一些文字,并不重要,这里我们应该关注的点是:该如何处理好node的路由

	//app.js
	var http = require("http");	//引入http模块
	var fs = require("fs");//引入fs模块 用于文件读取
	var httpServer = http.createServer();	//创建服务

	httpServer.on("request",(req,res)=>{
		//为了判断访问什么文件,需要获取当前路径
		var currentUrl = req.url
		// res.setHeader("Content-Type","charset=utf-8")
		//请求"/"加载留言板列表
		if(currentUrl =="/"){
			fs.readFile("./view/index.html","utf8",(err,data)=>{
				if(err) res.end("404 not  found");
				res.write(data);
				res.end();
			})
		}else if(currentUrl =="/add"){
			fs.readFile("./view/add.html","utf8",(err,data)=>{
				if(err) res.end("404 not  found");
				res.write(data);
				res.end();
			})
			//判断是否能与'/public'匹配,若成功,则渲染出来
		}else if(currentUrl.indexOf("/public") === 0){
			console.log(currentUrl);
			fs.readFile('./'+currentUrl,"utf8",(err,data)=>{
				if(err) res.end("404 not  found");
				res.write(data);
				res.end();
			})
		}else{
			console.log(currentUrl);
			fs.readFile("./view/404.html","utf8",(err,data)=>{
				if(err) res.end("404 not  found");
				res.write(data);
				res.end();
			})
		}
		//请求"/add"加载留言板添加
		//检测静态资源并响应
		//否则404
	})
	//4.启动服务
	httpServer.listen(8000,()=>{
		console.log("启动成功,即将访问:http://localhost:8000");
	})
	
	//-----404.html
	

最终结果

	var http = require("http");	//引入http模块
	var url = require("url");	//引入url模块 处理路径
	var fs = require("fs");//引入fs模块 用于文件读取
	var querystring = require("querystring");//引入fs模块 用于文件读取

	var httpServer = http.createServer();	//创建服务
	
	var msg = [ 
		{name:"张三",content:"hello,我叫张三"},
		{name:"李四",content:"hello,我叫李四"},
		{name:"王五",content:"hello,我叫王五"}
	]
	httpServer.on("request",(req,res)=>{
		//为了判断访问什么文件,需要获取当前路径
		var currentUrl = req.url
		// res.setHeader("Content-Type","charset=utf-8")
		//请求"/"加载留言板列表
		if(currentUrl =="/"){
			fs.readFile("./view/index.html","utf8",(err,data)=>{
				var str = "";
				msg.forEach((item=>{
					str +=`<li>姓名:${item.name} .他说:  ${item.content}</li>`					
				}))
				var data = data.replace("li填充",str)
				if(err) res.end("404 not  found");
				res.write(data);
				res.end();
			})
			//请求"/add"加载留言板添加
		}else if(currentUrl =="/add"){
			fs.readFile("./view/add.html","utf8",(err,data)=>{
				if(err) res.end("404 not  found");
				res.write(data);
				res.end();
			})
			//判断是否能与'/public'匹配,若成功,则渲染出来
		}else if(currentUrl.indexOf("/public") === 0){
			console.log(currentUrl);
			fs.readFile('./'+currentUrl,"utf8",(err,data)=>{
				if(err) res.end("404 not  found");
				res.write(data);
				res.end();
			})
		}else if(currentUrl.indexOf('/doadd') == 0){
			console.log(req);
			//数据处理 
			//首先判断请求的方式  可使用req.request方法
			if(req.method == "POST"){				
				//注意 : 使用post请求时,数据量可能很庞大,因此分片获取
				//说明 :	 data事件 -- 数据正在传输中, end事件 -- 数据传输完毕
				var postData = "";
				req.on("data",(chunk)=>{
					postData +=chunk;
				});
				req.on("end",function(){
					paramobj = querystring.parse(postData);
					msg.push(paramobj)																
					//3.跳转
					res.statusCode = 302;
					res.setHeader("Location","/");
					res.end();
				});
			}else{
				//1.接收数据
				var paramobj = url.parse(req.url,true).query
					// console.log(paramobj);  先打印观察数据格式
					
				//2.入库(此时没有数据库,我们直接将数据压入msg中 
				msg.push(paramobj)											
				
				//3.跳转
				res.statusCode = 302;
				res.setHeader("Location","/");
				res.end();
			}
		}else{
			console.log(currentUrl);
			fs.readFile("./view/404.html","utf8",(err,data)=>{
				if(err) res.end("404 not  found");
				res.write(data);
				res.end();
			})	
		}
		
		//检测静态资源并响应
		//否则404
	})

	//4.启动服务

	httpServer.listen(8000,()=>{
		console.log("启动成功,即将访问:http://localhost:8000");
	})

npm指令

  • npm -v :版本查询

  • npm init 项目初始化 ( 生成package.json文件) 注意: .json文件 不可以添加任何注释 否则报错

  • npm install 包名 --save-dev (npm install 包名 -D):注意 安装的包只用于开发环境,不用于生产环境

  • npm install 包名 --save 安装的包需要发布到生产环境的
    安装完毕后在你的文件夹中会出现多出一个node_modules的文件夹和package-lock.js的文件,在node_modules文件夹中会有子文件夹为你刚刚安装的包,在package.js中也会出现刚刚安装的文件以及版本号

  • npm ls 查看安装的模块

  • npm help 查看某条命令的详细帮助

Buffer(缓冲区)

1.Buffer的结构和数组很像,操作方法也很类似
2.数组中 不能存储二进制文件,而buffer就是弥补数组的这种缺陷。我们可以将几乎所有的文件类型转变成二进制文件存储,这也显示除buffer的易用
3.使用buffer不需要引入模块,直接使用即可
4.虽然buffer中所有的数据都是二进制,但却是以16进制显示(2进制太长)

buffer中存储的每一个元素的范围是00 - ff 0-255
00000000 - 11111111
计算机 一个 0 或者一个 1 表示一位(bit)
8bit -----> 1byte字节

var str = "today is thursday"

将一个字符串保存到buffer中

var buf = Buffer.from(str);
console.log(buf);

得到

<Buffer 74 6f 64 61 79 20 69 73 20 74 68 75 72 73 64 61 79>  

// 这其中的每一个数字都是16进制,虽然说buffer需要存储二进制,但是计算机中 所有进制都会转变成16进制 ,便于保存(2位数,如果是2进制则需要更多位)

注意 :buffer所有构造函数,都不推荐使用 因为很多都已经被废弃,存在着隐患

alloc 方法 : 分配一个大小为 size 字节的新建的Buffer.

使用alloc为变量buf2 分配大小

Buffer 一旦创建, 大小是不可以被改变的,实际上,Buffer是对底层内存的操作

var buf2 = Buffer.alloc(10);	

为第 0 位索引赋值为 88

buf2[0] = 88;
console.log(buf2);

注意: 每个索引分配的值 最好是连续的 ,便于查找,对性能有帮助

Buffer.allocUnsafe(size) 创建一个指定大小的buffer,但是buffer中可能含有敏感数据

var buf3 = Buffer.allocUnsafe(10);
console.log(buf3);   

注意 与alloc不同的是, allocunsafe只是分配一个连续的10位空间,他并不会将每一位中的数据清除(内存是反复使用的,所以这些遗留的数据是上一次未清除的)


分割线


关于fs 受从操作文件的步骤(这里给出的列子都是同步执行)

	// 1.打开文件
		fs.openSync(path,flags[,mode])
		/* - path  要打开的文件路径
		 - flags 打开文件需要做的操作的类型
			r : 只读
			w : 只写
			- mode 设置文件的操作权限,一般不传
			
		 返回值:
		 	- 该方法会返回一个文件的描述符作为结果, 我们可以通过该描述符来对文件进行各种操作
	 2.向文件中写入内容
		 -fd 文件的描述符
		 -string  要写入的内容
*/
fs.writeSync(td,string[,position[,encoding]])
	// td - 写入哪个文件
	// string  写入的字符串
	// position  从什么位置开始写入
	// encoding  编码格式
	// 3.保存并关闭文件
	

EG:

	// 导包
	var fs = require("fs")
	
	// 打开文件
	var file = fs.openSync("hello.txt","w")
	
	// 写入文件
	fs.writeSync(file,"今天天气很好");
	
	// 保存并关闭文件,释放内存
	fs.closeSync(file);
// 完成

关于fs 受从操作文件的步骤(这里给出的列子都是异步执行)

	var fs = reqiure("fs");
	fs.open("text.txt","w",function(err,fd){
		// 异步读写操作 
			// 第一个参数 :需要操作的文件名
			// 第二个参数 : 写操作
			// 第三个参数 : 回调函数
				// 回调函数 :err , 打开的文件赋予的变量名(以下操作变量名即可)
		if(!err){
			fs.write(fd,"执行异步读写操作"function(err){
				if(!err){
					// 打印提示 写入成功
					console.log("成功写入")
				}
				// 成功写入后 需要关闭文件,释放内存
				fs.close(fd,function(err){
					if(!err){
						console.log("成功关闭")
					}
				})
			})		
		}
	})
	
	//  这一句永远在另外两条console语句之前打印,因为open是异步操作的
	console.log("异步执行")

有个悲伤的故事,前面两种方式比较麻烦我们基本不用,下面介绍一个简单读写方式 ?…

	var fs = require("fs");
	fs.writeFile(file,data[,options],callback)		//  异步
	fs.writeFileSync(file,data[,options])				//  同步
	/*
		- file  要写入的文件路径
		- data  要写入的数据
		- options 选项,可以对写入进行 一段设置
		- callback 回调函数
	*/  
	// 这种写法不需要 打开文件,也不需要关闭文件
	EG:
		fs.writeFile("text.txt","这是我们需要写入的数据"function(err){
			if(!err){
				console.log("写入成功")
			}
		})

上述的writefile已经将所有的需要操作进行了封装,因此我们不需要再重复操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值