目录
前言:Nodejs做服务器端的开发,而前端学习node,可以设计一个服务器,进行一些前端请求参数的测试。
一.介绍
1.简介
Node.js 是⼀个基于 Chrome V8 引擎的 JavaScript 运⾏时。
Node.js 是⼀个开源与跨平台的 JavaScript 运⾏时环境。 它是⼀个可⽤于⼏乎任何项⽬的流⾏⼯具!
Node.js 在浏览器外运⾏ V8 JavaScript 引擎(Google Chrome 的内核)。 这使 Node.js 表现得⾮常出⾊。
Node.js 应⽤程序运⾏于单个进程中,⽆需为每个请求创建新的线程。 Node.js 在其标准库中提供了⼀组异步的 I/O 原⽣功能(⽤以防⽌ JavaScript 代码被阻塞),并且 Node.js 中的库通常是使⽤⾮阻塞的范式编写的
(从⽽使阻塞⾏为成为例外⽽不是规范)。
当 Node.js 执⾏ I/O 操作时(例如从⽹络读取、访问数据库或⽂件系统),Node.js 会在响应返回时恢复操作,⽽不是阻塞线程并浪费 CPU 循环等待。
这使 Node.js 可以在⼀台服务器上处理数千个并发连接,⽽⽆需引⼊管理线程并发的负担(这可能是重⼤bug 的来源)。
Node.js 具有独特的优势,因为为浏览器编写 JavaScript 的数百万前端开发者现在除了客户端代码之外还可以编写服务器端代码,⽽⽆需学习完全不同的语⾔。
在 Node.js 中,可以毫⽆问题地使⽤新的 ECMAScript 标准,因为不必等待所有⽤户更新其浏览器,你可以通
过更改 Node.js 版本来决定要使⽤的 ECMAScript 版本,并且还可以通过运⾏带有标志的 Node.js 来启⽤特定
的实验中的特性。
⼤量的库
npm 的简单结构有助于 Node.js ⽣态系统的激增,现在 npm 仓库托管了超过 1,000,000 个可以⾃由使⽤的开源库包。
2.Nodejs简史
Nodejs诞⽣与2009年,JavaScript 是⼀⻔被创建于 Netscape(作为⽤于在其浏览器 Netscape Navigator 中操纵⽹⻚的脚本⼯具)中
的编程语⾔。
Netscape 的商业模式的其中⼀部分是出售 Web 服务器,其中包括⼀个被称为 Netscape LiveWire 的环境,该
环境可以使⽤服务器端 JavaScript 创建动态⻚⾯。 不幸的是,Netscape LiveWire 并不⼗分成功,并且服务器
端 JavaScript 也没有普及,直到引⼊了 Node.js。
引领 Node.js 兴起的⼀个关键因素是时机。 仅仅⼏年前,多亏 "Web 2.0" 应⽤程序(例如 Flickr、Gmail 等)向世界展示了 Web 上的现代体验,JavaScript 开始被视为⼀种更为严肃的语⾔。
随着许多浏览器竞相为⽤户提供最佳的性能,JavaScript 引擎也变得更好。 主流浏览器背后的开发团队都在努⼒为 JavaScript 提供更好的⽀持,并找出使 JavaScript 运⾏更快的⽅法。 多亏这场竞争,Node.js 使⽤的
V8 引擎(也称为 Chrome V8,是 Chromium 项⽬开源的 JavaScript 引擎)获得了显着的改进。
Node.js 恰巧构建于正确的地点和时间,但是运⽓并不是其今天流⾏的唯⼀原因。 它为 JavaScript 服务器端
开发引⼊了许多创新思维和⽅法,这已经对许多开发者带来了帮助。
3.Nodejs优点
- 运⾏在V8JavaScript引擎上(⾼性能)
- 事件驱动
- ⾮阻塞的IO模型
- 丰富的⽣态圈(npm下载资源)
二.安装
1.Nodejs
简单粗暴,直接官网下载无脑安装(最后的那个勾选框那个不要选,选了自动安装很多东西到你的系统盘!),左边那个是稳定版,右边那个是包含新特性的版本。
输入node -v显示node.js的版本说明已安装成功
输入npm-v显示npm版本说明自带的npm也己经安装成功
npm的作用就是对Node.js依赖的包进行管理,也可以理解为用来安装/卸载Node.js需要装的东西。
我参考了这篇文章
2.VSCode
无脑安装
VSCode快捷键:
三.全局对象
这里只是举例讲解一下,更多请自己看在线api(戳下面)
在终端中使用node命令运行JS脚本:
,即node+文件名(.js可加可不加)
Nodejs提供了很多全局对象,这些对象可以直接使⽤,不需要做单独的引⼊例如:
在js中的⽇志信息打印就是其中之⼀,
console.log("hello world!");
console.info("信息");
console.error("报错");
输出:
定时器也是其中之⼀,
//延迟执行,3s之后执行函数
setTimeout(function(){
console.log("timer");
},3000)
//间隔执行,每隔1s执行一次函数
// var i=0;
// setInterval(function(){
// i+=1;
// console.log(i);
// },1000)
var time=0;
var timer=setInterval(function(){
time+=2;
console.log("timer="+time);
if(time>6){
clearInterval(timer);
}
},1000)
console.log(__dirname);//打印出来当前的路径
console.log(__filename);//打印出来当前路径(包含文件名)
输出:
输入命令行命令时,可用tab键补全。
四.回调函数
我们需要熟悉⼀下回调函数,因为在整个Nodejs中,慢慢的都是回调函数
//两个比较传统的函数声明方式
function sayHi(){
console.log("hi");
}
var sayBye= function(name){
console.log(name+":bye");
}
//调用执行
// sayHi();
// sayBye();
//回调函数
function callFunction(callback,name){
callback(name);
}
//调用执行,在回调函数中传入函数名,进而调用函数
//callFunction(sayBye,"kd")
//回调函数的另一种方式
callFunction(function(name){
console.log(name+":bye");
},"frank");
五.模块(Commonjs规范)
在JavaScript的ES5版本中,最⼤的问题就是没有模块的概念,但是nodejs中,增加了commonjs规范来处理这⼀问题。
util.js:
//加和函数
var adder=function(a,b){
//注意这里不是的单引号,而是键盘左上角的那个顿号,这样才能使用ES6新特性$
return `this num of the numbers is ${a+b}`;
}
//计算数组长度函数
/*
var counter=function(arr){
return "there are "+arr.length+" elements in the array";
}
*/
//导出(方式一)
//module.exports=counter
//导出方式二(下面的写法默认是导出了一个对象{counter,adder})
/*
module.exports.counter=counter
module.exports.adder=adder
*/
//像下面写更为简洁
/*
module.exports={
counter:counter,
adder:adder
}
*/
//ES6新特性:前后一致的话可以只写一个,于是又有下面
module.exports={
//也可以在导出时定义函数
counter:function(arr){
return "there are "+arr.length+" elements in the array";
},
adder
}
index.js:
//导入文件(方式一)
//const counter=require("./util.js");
//导入(方式二)
const utils=require("./util.js");
//ES6导入方式
//import utils from "./util.js"
console.log(utils.counter([10,20,30]));
console.log(utils.adder(100,200));
运行index.js输出:
there are 3 elements in the array
this num of the numbers is 300
六.事件
⼤多数 Node.js 核⼼ API 构建于惯⽤的异步事件驱动架构,其中某些类型的对象(⼜称触发器,Emitter)会触发命名事件来调⽤函数(⼜称监听器,Listener)。
例如,net.Server 会在每次有新连接时触发事件,fs.ReadStream 会在打开⽂件时触发事件,stream会在数据
可读时触发事件。
所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象有⼀个 eventEmitter.on() 函数,⽤于将⼀个或多个函数绑定到命名事件上。 事件的命名通常是驼峰式的字符串,但也可以使⽤任何有效的 JavaScript 属性
键。
当 EventEmitter 对象触发⼀个事件时,所有绑定在该事件上的函数都会被同步地调⽤。 被调⽤的监听器返回的任何值都将会被忽略并丢弃。
直接使用事件:
//Nodejs中的事件和ES5中的时间不太一样,Nodejs中是代码触发,而ES5是手动触发
//导入事件模块
var events=require("events");
//创建事件对象
var myEmitter=new events.EventEmitter();
//设置事件监听器,someEvent等价与ES5中的事件,比如click事件
//但这里的someEvent不是已有事件的名字,而是自己自定义的名字
myEmitter.on("someEvent",function(message){
console.log(message);
});
//出发事件
myEmitter.emit("someEvent","the event was emitted");
类继承事件,使对象监听
//导入模块
var events=require("events");
var util=require("util");
//ES5创建类的方式
var Person=function(name){
this.name=name;
}
//使Person类继承事件
util.inherits(Person,events.EventEmitter);
var xiaoming=new Person("xiaoming");
var lilei=new Person("lilei");
var person=[xiaoming,lilei];
//循环为每个对象设置事件监听器
person.forEach(function(item){
item.on("speak",function(message){
console.log(item.name+" say:"+message);
})
})
xiaoming.emit("speak","hi");
lilei.emit("speak","my name is lilei");
上面的代码ES6的写法:
const EventEmitter=require('events');
class Person extends EventEmitter{
constructor(name){
super();
this.name=name;
}
}
var xiaoming=new Person("xiaoming");
var jack=new Person("jack");
var person=[xiaoming,jack];
person.forEach(function(item){
item.on("speak",function(message){
console.log(item.name+" say:"+message);
})
});
xiaoming.emit("speak","hi");
jack.emit("speak","my name is jack");
输出:
xiaoming say:hi
jack say:my name is jack
七.文件读写
1.设置vscode中nodejs代码提示
注意一定要在当前项目路径下安装,否则无效!
设置成功后会在当前目录下自动生成一个json文件 以及一个node_modules文件夹。
2.同步读写操作
//导入文件模块
var fs=require("fs");
//同步读取(readFileSync是同步读取函数,Sync代表同步)
var readMe =fs.readFileSync("./readMe.txt","utf-8");
//将readMe文件中的内容同步写到wirteMe中,如果没有就创建一个writeMe文件
fs.writeFileSync("writeMe.txt",readMe);
//查看是否同步,因为读写耗时,所以如果是同步进行读写操作,那么finished会在最后输出
console.log(readMe);
console.log("finished");
3.异步读写操作
(1)异步读
上述代码的打印与之前完全相反,先打印
finished
,然后输出
data
数据,此时就是异步效果
我们对耗时的代码⼀定要进⾏处理,否则我们的主线程则处于卡顿的等待过程,如下代码
我们做了⼀个4秒的等待,所以,打印需要在4秒之后才会出现。这就是卡顿的效果,如果使用同步操作⽤户体验⼀定是极差的
var fs=require("fs");
//readFile是异步读取操作,不加Sync即是异步
//第三个参数是回调函数
var readMe=fs.readFile("./readMe.txt","utf-8",function(err,data){
console.log(data);
})
//等待4s
var waitTill=new Date(new Date().getTime+4*1000);
while(waitTill>new Date()){}
console.log("finished");
输出:
finished
Hello FileSystem!
(2)异步写
var fs=require("fs");
var readMe=fs.readFile("./readMe.txt","utf-8",function(err,data){
fs.writeFile("./writeMe.txt",data,function(){
console.log("写入数据完成!");
})
})
console.log("finished");
输出:
finished
写入数据完成!