这是我参与8月更文挑战的第8天,活动详情查看: 8月更文挑战
NODE.JS
一、基本概述
1.概述
1)对比JavaScript和node.js
JS运行在客户端浏览器,存在多个解释器,存在代码兼容性;Nodejs运行在服务器端,只有一种解释器,不存在兼容性
两者都有相同的内置(ES)对象,自定义对象,不同的宿主对象
JS用于开发浏览器端的交互效果,Nodejs用于服务器端开发,数据库的操作,文件的操作,其它服务器的调用...
2)相关网站
nodejs.org 英文官网
nodejs.cn 中文镜像
3)运行方式
脚本模式
node 拖拽文件 回车
交互模式
node 回车 进入到交互模式
两次ctrl+c 退出交互模式
4)node.js特点
支持数万个并发连接,常用于基于社交网络的大规模WEB应用
本身属于是单线程运行,不适合那些CPU密集型的操作
2.全局对象
1)global
在Nodejs下全局变量和全局函数都是可以使用global来访问到的。
2)console
log() 打印日志
info() 打印消息
warn() 打印警告
error() 打印错误
time() 开始计时
timeEnd() 结束计时
开始计时和结束计时提供的参数要保持一致
3)process
| 进程 | |
|---|---|
| arch | 查看当前的CPU架构 |
| platfrom | 查看当前的操作系统 |
| version | 查看当前node.js版本号 |
| pid | 查看当前进程编号 |
| kill() | 结束指定编号的进程 |
4)Buffer
缓冲区、缓冲器,在内存中临时存储数据的区域,常用于存储网络传输的资源
let buf=Buffer.alloc(5, 'abcde'); //创建buffer,分配5个字节空间,存储数据
一个英文字母占1个字节,一个汉字占3个字节
String(buf) / buf.toString() //转为字符串
二、基本模块
模块是一个功能体
一个模块引入其它的模块,一个模块被其它的模块所引入
分为自定义模块、核心模块、第三方模块
| Nodejs自动给每个模块添加了一个函数,文件中的代码自动被函数所包含,里边的变量和函数都是局部的,所形成的作用域称为模块作用域。 (function(){ 文件中的代码 }) |
|---|
| module.exports 公开的内容,也就是导出的对象,引入该模块会得到这个对象 |
| require() 是一个函数,用于引入其它的模块 |
1.模块相关
require: 是一个函数,用于引入其它模块
module: 当前模块的对象
module.exports: 当前模块的导出对象
__dirname: 当前模块的绝对目录 directory
__filename: 当前模块的绝对目录和模块名称
2.模块分类
| 以路径开头 | 以路径开头 | |
|---|---|---|
| 文件模块 | require('./circle.js') 常用于引入自定义模块 | require('url') 常用于引入官方提供的核心模块 |
| 目录模块 | require('./02_dong') 首先会到02_dong目录下寻找package.json文件中寻找main对应的文件,如果没有则会自动寻找index.js | require('ran') 会自动到当前目录下node_modules目录中寻找,如果找不到会一直往上一级目录下的node_modules中寻找。用于引入第三方模块 |
../上一级
a/ 下一级
论述:如果执行require('mysql'),是如何引入模块的。
会到当前目录下的node_modules中寻找mysql目录,如果找不到,会一直往上一级目录下的node_modules中寻找mysql目录;找到后,接着到mysql目录下去寻找package.json中main对应的文件,如果找不到会自动去寻找index.js
3.npm和包
包(package): 是第三方模块
npm:是用来管理包的工具,包含下载安装、更新、卸载、上传...
npm在安装nodejs的时候会附带的安装
npm -v 查看版本号
1)切换命令行目录
①cd 目录的路径 回车
盘符名称: 例如d: 如果涉及到盘符的变化需要运行这一步
②在要进入的目录下空白区域,按住shift,单击鼠标右键,选择'在此处打开powershell窗口'
2)npm下载安装
npm install 包的名称 回车
会将下载的包放入到node_modules中,如果node_modules目录不存在会自动创建。同时会生成文件package-lock.json,用于记录包的版本号。
4.查询字符串模块(querystring)
查询字符串:浏览器向服务器发请求,传递数据的一种方式,位于网址(URL)中
查询字符串模块是用来操作查询字符串的工具
parse() 将查询字符串解析为对象,可以获取传递的数据了
5.URL模块
URL: 互联网上的资源都有对应的网址,这个网址就称为URL
www.codeboy.com:9999/products.ht…
协议 域名/IP地址 端口 文件的路径 查询字符串
URL模块用于操作URL
parse() 将URL解析为对象,获取各个部分 查询字符串部分(query)
6.定时器
1)一次性定时器
let timer=setTimeout(()=>{
console.log('boom!');
},3000);
//清除
clearTimeout(timer);
/*
三秒打印,clearTimeout这条是清除所以会不显示打印内容。
3000是秒
*/
2)周期定时器
let timer=setInterval(() => {
console.log('boom');
//每打印1次加1
i++;
//当i为3的时候,清除定时器
if (i === 3) {
clearInterval(timer);
}
}, 3000);
/*
如果写的是一次性定时器,则不能进行循环直接打印一次
*/
3)立即执行的定时器
console.log(2);
setImmediate(() => {
console.log(1);
});
process.nextTick(() => {
console.log(4);
});
console.log(3);
/*
2
3
4
1
*/
7.文件系统模块(fs)
在nodejs下文件包含文件形式和目录形式
使用前需要先引入模块
const fs=require('fs');//名字叫什么都行
1)查看文件的状态
isDirectory() 是否为目录
isFile() 是否为文件
fs.stat( 文件的路径, 回调函数 ) / fs.statSync( 文件的路径 )
回调函数 用于获取结果
err 可能产生的错误
s 获取到的状态对象
//同步、
console.log(fs.statSync("文件名"));
//异步
fs.stat("文件名",(err,s)=>{
if(err){
throw err;
}
console.log(s);
/*
console.log(s.inFile());
console.log(s.isDirectory());
*/
})
2)创建目录
fs.mkdirSync( 目录的路径 )
fs.mkdirSync("./com1");
fs.mkdir("./com2", (err) => {
if (err) {
throw err;
}
})
3)移除目录
fs.rmdirSync( 目录的路径 )
fs.rmdirSync("./com1");
fs.rmdir("./com2", (err) => {
if (err) {
throw err;
}
})
4)读取目录
fs.readdir(文件的路径, 回调函数) / fs.readdirSync(文件的路径)
回调函数
err 可能产生的错误
result 读取到的目录结果,格式为数组
console.log(fs.readdirSync("文件路径"));
fs.readdir("文件路径",(err,s)=>{
console.log(s);
})
/*
打印出文件夹中的东西
*/
5)写入文件
(1)覆盖写入
fs.writeFile(文件的路径, 数据, 回调函数) / fs.writeFileSync( 文件的路径,数据 )
如果文件不存在,则创建文件然后写入数据
如果文件已经存在,会覆盖原来的内容写入
fs.writeFileSync("文件名", "覆盖内容");
fs.writeFile("文件名", "覆盖内容", (err) => {});
(2)追加写入
fs.appendFile(文件的路径, 数据, 回调函数) / fs.appendFileSync(文件的路径, 数据)
如果文件不存在,则创建文件然后写入数据
如果文件已经存在,在末尾追加写入内容
fs.appendFile("文件名", "需要追加的内容", (err) => {});
fs.appendFileSync("文件名", "需要追加的内容");
6)读取文件
fs.readFile(文件的路径, 回调函数) / fs.readFileSync(文件的路径)
fs.readFile("1.txt", (err, s) => {
console.log(s.toString());//转字符,否为为buffer乱码
});
console.log(fs.readFileSync("1.txt").toString());
7)删除文件
fs.unlink(文件的路径,回调函数) / fs.unlinkSync(文件的路径)
fs.unlinkSync("1.txt");
fs.unlink("1.txt", (err) => {});
8)检测文件是否存在
fs.existsSync(文件的路径)
//使用循环的方法进行查看是否存在
if (fs.existsSync("./ko")) {
console.log("ok");
}
9)拷贝文件
fs.copyFile( 源文件的路径, 目标文件的路径, 回调函数 ) / fs.copyFileSync(源文件的路径, 目标文件的路径)
fs.copyFile("1.js", "2.js", (err) => {});
fs.copyFileSync("1.js", "3.js");
10)文件流
createReadStream(文件的路径) 创建可读取的文件流
createWriteStream(文件的路径) 创建可写入的文件流
8.同步和异步
同步:在运行的过程中,会阻止后续代码的执行,只有运行完才能往后执行,通过返回值来获取结果
异步:在运行的过程中,不会阻止后续代码的执行,在一个独立的线程执行,执行完以后将结果以回调函数的形式放入到事件对列,通过回调函数来获取结果。
三、web服务
1.http
http协议是浏览器和web服务器之间的通信协议
1)通用的头信息
Request URL: 请求的URL,向服务器端请求的资源
Request Method: 请求的方法 get/post
Status Code: 响应的状态码
1**: 正在响应,还没有结束
2**: 成功的响应
3**: 响应的重定向,跳转到另一个URL
4**: 浏览器端请求错误
5**: 服务器端错误
2)响应的头信息
Content-Type: 设置响应的内容的类型 html -> text/html
Location: 跳转的URL,通常会结合着状态码3**使用
3)请求的头信息
4)请求主体
表单传递的数据,如果没有数据此项为空
5)创建web服务器
//引入http模块
const http=require('http');
//创建web服务器
const app=http.createServer();
//设置端口
app.listen(8080);
//根据浏览器的请求作出响应
//通过事件作出响应
app.on('request',(req,res)=>{
//req 请求的对象
//req.url 获取请求的URL
//req.method 获取请求的方法
console.log(req.url, req.method);
//res 响应的对象
//参数1:设置响应状态码
//参数2:可选的,设置响应的头信息
//res.writeHead(302,{
// Location:'http://www.tmooc.cn'
//});
//设置响应的内容
res.write('这是你的jianbing');
//结束并发送响应
res.end();
});
2.ExPress
1)创建web服务器
const express=require('express');
const app=express();//将express模块导出
app.listen(8080);//设置web服务器端口
2)路由
用来处理特定的请求,包含有请求的方法、请求的URL、回调函数。
只有请求的方法和请求的URL同时匹配,才会执行回调函数。
res 响应的对象
res.send() 设置响应的内容并发送
res.sendFile() 设置响应的文件并发送,文件需要使用绝对路径 __dirname
res.redirect() 设置响应的重定向,跳转另一个URL
req 请求的对象
req.method 获取请求的方法
req.url 获取请求的URL
req.query 获取查询字符串传递的数据,格式为对象
app.get('需要响应的网页地址',(res,req)=>{
res.send();
res.sendFile('完整的目录');
res.sendFile(__dirname+'在同一目录下需要转的文件');
res.redirect('http://www.baidu.com');
})
| 对比get和post两种请求方法 |
|---|
| get请求传递的数据以查询字符串传递,可能被浏览器所缓存,速度相对块,传递的数据不超过4k |
| 传递方式 | 格式 | 获取 |
|---|---|---|
| get传递 | 查询字符串 | req.query 格式为对象 |
| post传递 | 流(不可见) | 通过事件获取 req.on('data', (chunk)=>{ //chunk是分段的数据,格式为buffer,需要转字符串,转完后为查询字符串,需要解析为对象 }) |
| 路由传参 | 通过URL | req.params 格式为对象 |
路由传参
导入express后使用
app.get('需要访问的地址',(req,res)=>{
res.send('访问成功');//可以用来测试是否成功
})
3.路由器
项目开发中,可能出现不同模块下相同的URL,为了团队协作,独立出每个功能模块,使用路由器将当前模块下所有的路由放到一起,并给URL添加前缀,最后挂载到web服务器下
//创建路由器
const express=require('express');
const r=express.Router();
r.get('/list',(req,res)=>{
res.send('');//写入显示的内容
})
module.exports=r;
//在web服务器下引入访问并挂在
const userRouter=require('文件路径');//导入文件
//挂载路由器到web服务器下,添加前缀
//参数1:添加的前缀 /user 访问形式 /user/list
//参数2:要挂载的路由器
app.use('/user',userRouter);
4.中间件
中间件为路由服务的,用于拦截对路由的请求,也可以作出响应。
中间件分为应用级中间件、路由级中间件、内置中间件、第三方中间件、错误处理中间件
1)应用级中间件
app.use(url,(req,res,next)=>{})
url 表示要拦截的URL,对应路由中的URL,一旦拦截会自动执行回调函数
next 是一个函数,表示往后执行下一个中间件或者路由
2)路由级中间件
路由器的使用
app.use( '/product', productRouter )
3)内置中间件
托管静态资源(html,css,js,图像...)
当浏览器端请求文件,不需要通过路由去寻找文件,而是让浏览器自动到指定的目录下去寻找。
app.use( express.static('目录路径') )
4)第三方中间件
属于第三方模块,需要提前下载安装
使用body-parser将post请求数据解析为对象
//1.引入body-parser模块
const bodyParser=require('body-parser');
//2.使用body-parser中间件,会将所有post请求数据解析为对象
app.use( bodyParser.urlencoded({
//是否使用扩展的模块qs,true表示使用,false表示不使用,会自动使用querystring模块
extended: false
}) );
//3.在路由中获取对象格式数据
req.body
4.MySQL模块
nodejs操作mysql数据库的工具模块
下载安装 npm install mysql
1)创建普通链接
const c=mysql.createConnection( { } ) //需要提供mysql连接的相关内容
c.connect() // 测试连接,可以省略
c.query(sql命令, 回调函数) //要执行的SQL命令,通过回调函数获取结果
/*
回调函数
err 可能产生的错误
result 具体SQL命令的执行结果
*/
2)创建链接池
pool.query( SQL命令, 要过滤的数据, 回调函数 )
//要过滤的数据格式为数组,过滤完会自动替换到SQL命令中的占位符
pool.query('DELETE FROM emp WHERE eid=?',['5 or 1=1'],(err,result)=>{
if(err) throw err;
console.log(result);
});
具有攻击性:DELETE FROM emp WHERE eid=5 or 1=1;
1=1 所有的数据都满足这个条件
占位符(?): 会对用户提供的条件进行过滤,把具有攻击性的条件给删除。