Node.js是基于谷歌的V8引擎,是一种运行在服务器端的JS解释器,可以实现所有后端语言的功能,例如java,php等能做的Node.js也可以。
www.nodejs.org 官网
www.nodejs.cn 中文镜像
对比JS和Node.js
JS运行在客户端浏览器,存在多款浏览器有兼容性问题;Node.js运行在
服务器端,只能谷歌V8引擎一种解释器,不存在兼容性问题;
两者都有ES(内置)对象,自定义对象;不同的宿主对象。
JS用于开发浏览器端交互效果,Node.js用于服务器的操作,例如数据库访问,网络操作等…
Node.js适合做IO操作为主应用,不适合做CPU密集型的应用。
特点
Node.js属于单线程运行逻辑,默认只使用其中一个CPU内核
支持数万个并发连接,适合开发大规模的WEB应用
运行方式
脚本模式
node 拖拽文件 回车
交互模式
node 回车 进入交互模式
两次ctrl+c 退出交互模式
在说Node.js之前,咱们先来了解一下Node.js的基本操作
JS运行在客户端路蓝旗,存在多款浏览器,有兼容性问题;Node.js运行在服务器端,只有一种解释器,没有兼容性问题。
两者有共同的内置对象、自定义对象;以及各自宿主对象。
JS用于开发浏览器端的交互效果;Nodejs用于服务器端的开发,例如数据库访问、WEB服务器的创建…
官网:www.nodejs.rog
中文翻译:www.nodejs.cn
node -v
查看版本号
Node.js属于单线程运行逻辑,默认只使用其中一个CPU内核
支持数万个并发连接,适合开发大规模的WEB应用
脚本模式
node 拖拽文件
回车
交互模式
node 回车 进入交互模式
两次ctrl+c
退出交互模式
用于查看一个变量和函数是否为全局变量或者全局函数
global.变量 global.函数名称()
在node.js脚本文件中不是在全局作用域下,里边的变量和函数都是局部的,可以有效防止全局污染。
在JS脚本文件中是在全局作用域下,全局对象叫 window
,里边的变量和函数都是全局的,会存在全局污染。
例:编写脚本文件03_global.js,声明变量,创建函数;查看里边的变量和函数是否为全局的。
var a=1;
function func(){
return 3;
}
//nodejs下脚本文件不是全局作用域
//a和func都是局部的,不能使用global访问
console.log( global.func() ); //运行结果:不是全局的
console.log( ) 打印日志
console.info() 打印消息
console.warn() 打印警告
console.error( 打印错误
console.time( 开始计时
console.timeEnd() 结束计时
进程:计算机上每一个软件启动后都是有一个进程。
process.arch 查看当前CPU的架构
process.platform 查看当前的操作系统
process.version 查看当前node.js的版本号
process.pid 查看当前进程的编号
process.kill(进程编号) 结束制定编号的进程
Buffer:缓冲区、缓冲器,内存中存储数据的区域,常用于存储网络传输的资源。
let buf=Buffer.alloc(5,'abcde'); //创建buffer空间并存储数据,每个英文字符占1个字节,汉字占3个字节
buf.toString()//将buffer转为字符串
String(buf)//将buffer转为字符串
Node.js下,每个模块是一个功能体。
分为自定义模块
、核心模块
、第三方模块
每一个文件就是一个模块
module:当前模块的对象
require:是一个函数,用于导入另一个模块
module.exports:导出的对象,默认是一个空对象,如果要导出内容,需要放入到该对象。
__dirname:directory 当前模块的绝对路径
__filename:当前模块的绝对路径+模块名称
以路经开头 | 不以路径开头 | |
---|---|---|
文件模块 | require(’./circle.js’) 常用于引入自定义以内 |
require(‘querystring’) 用于引用官方提供的核心模块 |
目录模块 | require(’./02_dong’) 首先会到目录下寻找package.json文件中main对应的文件; 如果没有会自动赵找index.js |
equire(‘ran’) 首先会到当前目录下的node_modules目录中寻找ran目录; 如果找不到会一直往上一级的node_modules中寻找ran目录;常用于第三方模块** |
json文件:属于一种数据文件,通常放数组和对象,对象的属性名必须用双引号,字符串必须用双引号。
包:package,就是目录模块,也是第三方模块的叫法
npm:用于管理包的工具,包含有下载安装、升级、卸载、上传…
npm会在node.js安装时附带安装
npm -v
查看npm版本号
① cd 粘贴路径 回车
如果涉及到盘符的变化,需要添加 盘符名称:
回车
② 在指定的目录下的空白区域按住shift鼠标右击选择’在此处打开 powershell窗口’
网址:www.npmjs.com
npm installl 包名称
回车
将包自动放到node_modules目录中,这个 目录不存在自动创建。,可能会下载一些其他依赖的包。同时还会产生一个package-lock.json的文件,用于记录包的版本号。
查询字符串:浏览器向web服务器发送请求,传递数据的一种方式,位于URL中问号后的部分。
keyword=123&enc=utf-8
查询字符串模块用于操作查询字符串的工具模块。
parse()
将查询字符串解析为对象
例:获取以下查询字符串中商品的名称和价格:pname=apple&price=5199
const querystring=require('querystring');
var str='pname=apple&price=5199';
let obj=querystring.parse(str);
console.log(obj.pname);
console.log(obj.price);
URL:统一资源定位,网络上的任何资源都有对应的URL
http:// www.codeboy.com: 9999/ prodects.html? kw=dell
协议 域名/IP地址 端口 文件在服务器上的路径 查询字符串
URL模块用于操作 URL
parse()
将一个URL解析为对象,可以得到URL中的各个部分。
//开启
let timer=setTimeout(回调函数,间隔时间);
//当间隔时间到了,会调用一次回调函数,单位是毫秒
//清除
clearTimeout(timer);
//开启
let timer=setInterval(回调函数,间隔时间);
//每个一段时间,调用一次糊掉函数
//清除
clearInterval(timer);
例:两秒打印一次,打印3次后,清除定时器
let i=0;
let timer=setInterval(()=>{
console.log('boom');
i++;
if(i===3){
clearInterval(timer);
}
},2000);
//第一种
//开启
let timer=setImmediate(回调函数);
//清除
clearImmediate(timer)
//第二种
process.nextTick(回调函数)
文件包括文件形式和目录形式
fs.mkdirSync(目录的路径)
fs.rmdirSync(目录的路径)
statSync(文件的路径)/stat(文件的路径,回调函数)
回调函数:异步操作通过回调函数获取结果
err:可能产生的错误
s:具体的文件状态
s.isFile() 是否为文件
s.isDirectory 是否为目录
readdir(文件路径,回调函数)
获取的结果为数组形式
//异步
fs.readdir('../day02',(err,arr)=>{
if(err) throw err;
//读取的目录文件
console.log(arr);
});
console.log('运行结束');
let s=fs.readdirSync('../day02');
console.log(s);
console.log('运行结束');
wirteFileSync(文件的路径,写入的数据)
wirteFile(文件的路径,写入的数据,回调函数)
fs.writeFile('./1.txt','range',(err)=>{
if(err) throw err;
console.log('写入成功');
})
如果文件不存在,则会创建文件后写入文件
如果文件已经存在,则会原来基础上覆盖写入
appendFileSync(文件的路径,写入的数据)
/ appendFile(文件的路径,写入的数据,回调函数)
如果文件不存在,则会创建文件然后写入数据
如果文件已经存在,则会在文件的末尾追加写入数据
例:使用异步的方法往文件3.txt中追加写入数据 Hello你好
fs.appendFile('./3.txt','Hello你好',(err)=>{
if(err) throw err;
})
readFileSync(文件的路径)
/ readFile(文件的路径,回调函数)
读取的结果为buffer数据
//异步,读取stu.txt
fs.readFile('./stu.txt',(err,data)=>{
if(err) throw err;
console.log( String(data) );
});
//同步,读取3.txt
let s=fs.readFileSync('./3.txt');
console.log( String(s) );
unlinkSync(文件的路径)
/ unlink(文件的路径,回调函数)
例:使用异步方法删除1.txt
fs.unlink('./1.txt',(err)=>{
if(err) throw err;
})
existsSync(文件的路径)
true —> 存在 false—> 不存在
注:只能用同步 不能用异步
例:如果文件2.txt存在,则同步删除该文件;如果目录mydir2不存在,则同步创建该目录
if( fs.existsSync('./2.txt') ){
fs.unlinkSync('./2.txt');
}
if(!fs.existsSync('./mydir2')){
fs.mkdirSync('./mydir2')
}
copeFileSync(源文件,目标文件)
/ copeFile(源文件,目标文件,回调函数)
例:拷贝文件3.txt到mydir下
fs.copyFile('./3.txt','./mydir/3.txt',(err)=>{
if(err) throw err;
console.log('拷贝成功');
})
例:同步拷贝stu.txt到mydir下
let s=fs.copyFileSync('./stu.txt','./mydir2/stu.txt');
console.log('拷贝成功');
createRreadStream(文件的路径)
创建可读取的流对象
createWriteStream(文件的路径)
创建可写入的流对象
事件格式
on('事件名称',回调函数)
事件名称是固定用法,一旦触发事件自动执行回调函数
PS:pipe( )
管道,可以将读取的流添加到写入流
//同步:从上往下执行
let s=fs.statSync('../day02');
console.log(s);
//查看是否为文件
console.log(s.isFile());
//查看是否为目录
console.log(s.isDirectory());
同步打印的返回值会根据上述代码的书写顺序一致
let s=fs.stat('./01_homework.js',(err,s)=>{
//err,可能产生的错误
if(err){
throw err;
}
//s获取的文件的状态
console.log(s);
});
console.log('运行结束');
异步打印的返回值顺序会根据代码里各自逻辑的执行速度而定,哪个先执行完哪个先打印
下图是本次异步打印的结果,最下面的外层打印比上面的函数先执行完,所以外层先打印结果
浏览器和web服务器之间的通信协议
Request URL:请求的URL,像服务器端请求的内容
Request Method:请求的方法,get
/ post
Status Code:响应的状态码
1xx 系列:正在响应,还没有结束
2xx 系列:成功的响应
3xx 系列:响应的重定向,跳转到另一个URL
4xx 系列:客户端请求错误
5xx 系列:服务器端错误
Content-Type:相应的内容类型,html文件对应 text/html
Content-Length: 响应的文件长度,单位是字节
Location:要跳转的URL,需要结合着状态码3**使用
浏览器发出的叫做请求
传递的数据,例如注册、登陆传递数据
可有可无,没有传递数据,这项不显示。
可以创建web服务器,接收浏览器的请求并作出相应
const app=http.createServer(); //创建web服务器
app.listen(8080); //设置端口,用于访问web服务器
//添加事件,通过事件来接收请求并做出响应
app.on('request',(req,res)=>{
//req //请求的对象
//req.url //获取请求的url,对应端口号后的部分
//req.method //获取请求的方法
//res //响应的对象
res.write() //设置响应的内容
res.writeHead() //设置响应的状态码和头信息,第二个参数头信息可以为空
res.end() //结束并发送响应
})
一整套的解决方案,把用得到的功能都做到了并简化。express
基于Node.js
平台,快速、开放、极简的WEB开发框架
网址:www.expressjs.com.cn
下载:npm install express
//引入第三方模块
const express=require('express');
//创建web服务器
const app=express();
//设置端口
app.listen(8080);
浏览器向web服务器发送请求,web服务器端根据请求的方法和请求的URL做出响应,用来处理特定的请求。
路由的组成:请求的方法
、请求的URL
、回调函数(用来响应)
响应对象:
send()
设置响应的内容并发送
redirect()
设置响应的重定向,跳转到另一个URL
sendFile()
设置响应的文件,需要绝对路径 __dirname
例:根据表单提交的请求来创建对应的路由(post/mylogin),响应’登陆成功’
前端代码:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<h2>用户登陆h2>
<form method="POST" action="/mylogin">
用户:<input type="text" name="uname"><br>
密码:<input type="text" name="upwd"><br>
<input type="submit" >
form>
body>
html>
Node.js代码:
app.post('/mylogin',(req,res)=>{
//获取post请求的方法
//以流的方式传递,通过添加事件获取
//一旦数据流入,自动触发事件,通过回调函数获取数据
req.on('data',(chunk)=>{
console.log(chunk);//Buffer格式
let str=String(chunk);
console.log(str);
//查询字符串,解析为对象
let obj=querystring.parse(str);
console.log(obj);
})
res.send('登陆成功');
});
传递方式 | 类型 | 在路由中获取 |
---|---|---|
post传递 | 不可见 | req.on(‘data’,(chunk)=>{ chunk 就是获取的数据,格式为buffer,需要转字符串, 转字符串后为查询字符串,需要解析为对象 }) |
查询字符串传递 | 在URL中可见 kw=dell&price=4000 |
req.query 格式为对象 |
路由传参 | 在URL中可见 /package/mysql |
需要在路由的URL中指定形参 app.get(’/package/:pname’,(req,res)=>{ req.params //获取路由传参的数据,格式为对象 }) |
对比post和get的区别
post传递的数据不可见,get可见
post可以传递大文件,get方式只能通过url中传递字符串,长度不超过4k
post传递的速度相对get慢
通常登陆、注册使用post请求,搜索使用get请求
用来管理路由,将同一个模块下的路由归纳到一起;可以有效的进行分工协作,还可以防止URL冲突。
const express=require('express');
//创建路由器对象
const r=express.Router();
//往路由器下添加路由
r.get('/list',(req,res)=>{
res.send('这是用户列表');
});
//导出路由器对象
module.exports=r;
//引入自定义的模块user.js
const userRouter=require('./user.js');
//挂载并添加前缀
app.use('/user',userRouter);
用于拦截对路由的请求,最终是为路由服务的。
中间件分为应用级中间件、路由级中间件、内置中间件、第三方中间件、错误处理中间件
也称为自定义中间件,是一个中间件的函数,一旦拦截就会调用
app.use(要拦截的URL,回调函数)
在回调函数中有三个参数 req、res、next
next
表示往后执行,可能是下一个中间件或者路由
例:创建web服务器,添加用户数据列表的路由(get /list),响应’这是所有用户的数据’,添加中间件,拦截对URL为 /list的请求,验证用户是否为管理员,如果不是管理员root,则响应’请提供管理员账户’
// 引入第三方express模块
const express=require('express');
// 创建web服务器
const app=express();
// 设置端口
app.listen(8080);
//添加中间件,拦截对URL为 /list的请求
//一旦拦截调用回调函数
//中间件回调函数也有请求对象和响应对象
app.use('/list',(req,res,next)=>{
//获取查询字符串传递的数据
console.log(req.query);
//验证用户是否为管理员
//如果不是管理员root,则响应'请提供管理员账户'
if(req.query.uname!=='root'){
res.send('请提供管理员账户');
}else{
//往后继续执行,可能是中间件或者是路由
next();
}
});
app.get('/list',(req,res)=>{
res.send('这是所有用户的数据');
});
路由器的使用
app.use( URL,引入的路由器);
托管静态资源( html,css , js , img )
浏览器端向服务器端请求静态资源文件,不需要添加路由去寻找斌响应文件,而是将静态资源文件托管到指定的目录下,让浏览器自动去找。
app.use( express.static('目录的路径') )
例:创建web服务器,添加静态资源到public目录下,目录中添加登陆的网页login.html,点击提交向服务器发送请求( post /mylogin),创建对应的路由,获取用户和密码,并响应’登陆成功’
const express=require('express');
const querystring=require('querystring');
// 创建web服务器
const app=express();
// 设置端口
app.listen(8080);
// 添加静态资源到public目录下
app.use(express.static('./public'));
app.post('/mylogin',(req,res)=>{
req.on('data',(chunk)=>{
let obj=querystring.parse(String(chunk));
console.log(obj);
res.send('登录成功');
});
});
<h2>用户登录h2>
<form method="POST" action="/mylogin">
用户<input type="text" name="uname"><br>
密码<input type="password" name="upwd"><br>
<input type="submit">
form>
属于是第三方的模块
以body-parse
为例
下载安装:npm install body-parse
通常会伴随express
下载安装
//1.引入body-parser模块
const bodyParser=require('body-parser');
//2.使用body-parser中间件将post请求的数据解析为对象
app.use( bodyParser.urlencoded({
extended:false //是否使用扩展的qs,true表示使用 false会使用querystring
}) );
//3.在路由中获取数据,格式为对象
req.body
之所以把mysql模块单独拿出来说,是因为mysql模块是常用而且必会的
Nodejs 下用于操作mysql
数据库的模块
下载安装:npm install mysql
完整的连接
mysql.exe -h127.0.0.1 -P3306 -uroot -p
mysql.createConnection( )
mysql.createPool( )
query(SQL命令,回调函数)
通过回调函数获取结果
例:查询出emp数据表里编号为5的所有数据
pool.query('select * from emp where eid=5',(err,result)=>{
if(err) throw err;
console.log(result);
});
防止SQL注入,将用户提供的值进行过滤,过滤后再替换占位符
pool.query( 'select * from emp where eid=?',['5 or 3=3'],(err,result)=>{
if(err) throw err;
console.log(result);
} )