Author:@德玛玩前端
Date: 2023-07-06
Nodejs
一、Nodejs概述
1.1、什么是JavaScript
1995年由Netscape公司退出,后经ECMA统一标准的脚本语言。通常狭义上理解的JS是指在浏览器内置的JS解释器中运行的,主要用途是操作网页内容,实现用户交互
1.2、什么是Nodejs
2009年由Ryan Dahl开发,现由Nodejs Foundatuin维护,基于Google V8引擎的JS运行时环境,其运行完全脱离浏览器,可以编写独立的服务器端程序,主要用途为文件读写,网络访问,加密压缩,数据库操作等。
官网网站:www.nodejs.org
中文镜像网站:www.nodejs.cn
1.3 Javascript 和 Nodejs的区别
- 使js既可以编写客户端应用,又可以编写服务端应用了。一种语法统一前后端。
- 区别
- js属于客户端技术,运行在浏览器。nodejs是服务端技术,与PHP、JSP等是类似的技术
- js有多种解释器可以使用,如ie的chakra,ff的猴子系列,chrome的v8等等,nodejs运行于基于v8引擎改进而来的运行时环境
- js因为解释器有多种,所有存在代码兼容性问题,nodejs只有一种解释器,所以不存在代码兼容性问题。
- js 对象包括:ES原生对象,用户自定义独象,宿主对象(例如 DOM & BOM对象);nodejs 对象包括:ES原生对象,用户自定义对象,Nodejs扩展对象。
- js主要用于网页DOM元素的操作,实现用户交互效果,主要用于实现服务器端进行逻辑,如文件系统操作,数据库访问,其他服务器调用等。
二、安装和检测
-
安装步骤 【nodejs官方有安装说明支持】
-
安装后检测是否安装完成
widow + R
输入"cmd"
node -v
查看当前nodejs的版本号npm -v
附带的安装工具,查看版本号可检测node是否安装完成
-
进入交互模式
node + 回车
进入交互模式ctrl+c 两次 / exit
退出交互模式
-
交互模式和脚本模式的区别
- 交互模式(REPL模式 Read-Evaluate-Print-Loop )
- 读取用户输入,执行运算,输出执行结果,继续下一次循环
- 交互模式下,Nodejs自带的模块无需引入
- 脚本模式
- 将所有语句编写在独立的脚本文件中,一次性执行
- 脚本模式下,除了全局对象以其相关成员外,所有其他模块中声明的对象和方法必须使用require引入
- 交互模式(REPL模式 Read-Evaluate-Print-Loop )
三、Nodejs的体系结构
四、Node.js的语法
-
Nodejs语法是基于JavaScript的。下列内容与JS是完全一样的
- 数据类型
- 声明变量和常量
- 运算符
- 逻辑结构
- 函数作用域和闭包
- 对象和原型
- 对象分类
-
Nodejs的数据类型
-
原始类型(Primitive Type)
- string、number、boolean、null、undefined
-
引用类型 (Reference Type)
- ES核心对象 Global String Number Boolean Date Math Ar
ray Error Function Object RegExp - Nodejs对象:Buffer ReadStream ClientRequest
- 自定义对象
- ES核心对象 Global String Number Boolean Date Math Ar
-
五、Node.js的特点
- 简单,避免过渡设计
- 单线程逻辑处理
- 非阻塞的异步I/O处理
- 事件驱动编程
- 无锁机制,不会产生死锁
- 支持数万个并发连接 (承载访问量大,腾讯使用)
- Node.js适合搭建以IO操作为主,响应速度快,易于扩展的网络应用,例如
- 命令行工具
- 带有GUI界面的本地应用程序
- 交互式终端程序
- 基于社交网络的大规模web应用
- web socket服务器
- TCP/UDP套接字程序
- 客户端javascript编译器
- Nodejs不适合CPU密集型应用
- 深层次的嵌套和递归
- 复杂加密和解密算法
- 高可靠性运算
- 严格内存管理
- 数据挖掘和数据分析
六、Nodejs对象
6.1、global 全局对象
-
详见官网 https://nodejs.org/dist/latest-v14.x/docs/api/globals.html#globals_console
-
在交互模式下,声明的变量和创建的函数都是global下的,例如
global.a
global.fn()
-
在脚本模式下,声明的变量和创建的函数都不是global下的
// global.fn is not function
-
但是,在js下,声明的变量和创建的函数都是在全局window下,例如window.a、window.fn()
6.2、console对象
-
console.log()
打印日志 -
console.info()
打印消息 -
console.warn()
打印警告 -
console.error()
打印错误 -
console.time()
开始计时 -
console.timeEnd()
结束计时 //开始计时和结束计时的字符串要保持一致console.log(1); console.info(2); console.warn(3); console.error(4);//浏览器下看,nodejs下看不出区别 console.time('for') for(let i=1;i<10000;i++){ //..... } console.timeEnd('for')
-
小案例:查看相同情况下,for while do-while 哪一个更快
console.time('for') for(let i=1;i<=10000;1++){ } console.timeEnd('for') console.time('while') let i=1;//let 不能反复的声明变量 while(i<=10000){ i++ } console.timeEnd('while') console.time('do-while') i=1; do{ i++ }while(i<=10000) console.timeEnd('do-while')
6.3、process 进程对象
交互模式下使用
process.arch 查看当前cpu的架构
process.platform 查看当前的操作系统
process.version 查看当前的操作系统
process.env 查看当前计算机的环境变量有哪些
process.kill() 结束某个编号的进程
process.pid 查看当前进程的编号
6.4、Buffer对象
缓冲区:在内存中临时存储数据的区域,常用于网络传输时的资源,程序结束就消失。
//创建buffer
let buf=Buffer.allow(6,'23a22d')// 6个字符,存储的数据
//Buffer数据使用时需要转字符串
console.log(buf.tostring())//获取的buffer数据(unicode码)转字符串
//console.log(string(buf))
6.5、timer 定时器 (全局函数)
-
setTimeout(callback,delay) / clearTimeout(tiemr) 一次定时器
-
setInterval(callback,delay) / clearInterval(tiemr) 周期定时器
-
setImmediate(callback) / clearImmediate(tiemr) 立即执行器
-
process.nextTick(callback)
console.log(2) setImmediate(()=>{ console.log(1) }) process.nextTick(()=>{ console.log(4) }) //process.nexTick中的回调函数会放在主线程的最后 console.log(3) // 2 3 4 1
七、模块系统
-
模块:就是一个独立的功能体
-
分为3类:自定义模块,核心模块,第三方模块
-
Nodejs下规定,以一个文件就是一个模块,模块中的每一个变量和函数不能被web访问,模块中的代码被一个构造函数所包含,模块外部无法得到。
(function(exports,require,module,__filename,__dirname){ //代码 ............. })
-
引入模块往往用常量保存,常量名称通常就是模块的名字。
7.1、require()
用于引入另一个模块(对象)属性以及内容,同一级必须添加./
,后缀名可以省略。
7.2、exports
如果导出的对象为空,可以往对象中添加导出的内容。
案例:
创建两个模块,主模块main.js和功能模块circle.js,在功能模块下创建两个函数,传递半径计周长和面积,导出这两个函数;在主模块下引入,并调用两个函数。
//main.js
const circle=requrie('./circle.js') //引入一个模块默认都是对象
//console.log(circle)
console.log(circle.getArea(5).toFixed(2))
console.log(circle.getLength(5).toFixed(2))
console.log(circle.add(2,3))//5
//circle.js
function getArea(r){
return Math.PI*Math.pow(r,2)
}
function getLength(r){
return Math.PI*2*r
}
export.getArea=getArea
export.getLength=getLength //添加导出对象
exports.add=(a,b)=>a+b;
//exports={}
7.3、module
当前的模块对象
module.exports 当前模块要导出的对象
exports 导出对象的别名,等价于modules.exports
//都可以添加
exports.a=1
mpdules.exports.b=3
// 用一个新的对象作为导出对象
module.exports=emp
console.log(exports===module.exports) //false
7.4、__filename
当前模块的绝对路径+模块名称(文件名)
7.5、__dirname
当前模块的绝对路径 directory
7.6、require() 模块的引入
-
自定义模块
-
require('./cicrle.js')
// 路径方式引入js文件 -
require('./circle')
// 路径方式引入js文件,后缀名可以省略 -
require('./dir')
// 模块方式引入,需要初始化文件package.json
, 优先引入文件中main属性对应的文件名,默认是index.js
-
-
第三方模块
- 使用前提:npm下载到node_modules
- require(‘mysql’) 默认引入index.js
-
核心模块
- require(‘fs’)
- 直接引用 nodejs官网提供
八、核心模块(官方提供的内置模块)
8.1、querystring模块–查询字符串
查询字符串是什么?传递数据
浏览器向web服务器发送请求,传递数据的一种方式,位于URL中间号后的部分
http://www.baidu.com/list.html?username="dema" & age=22'
包含的api:
parse()
将查询字符串解析为对象
stringify()
将对象格式化为查询字符串
// 引入查询字符串模块
const qs=require('querystring') //自动从官方下载
let str="kw=dell&price=4999"
// 查询字符串解析为对象
let obj=qs.parse(str)
console.log(obj)
//将对象格式化为查询字符串
let obj2={
lid:18,
title:'dell'
}
let str2=qs.stringify(obj2)
console.log(str2) //lid=18&title=dell
8.2、URL模块–处理和解析URL
包含的Api:
parse()解析url为对象后,从而可以获得url中的任意部分
format() 将对象格式化为url,对象的字符串部分放的是对象
console.log(url.parse(str))
小案例:获取url中查询字符串的value值
// 思路
// 1. 引用url模块,将url转化成对象,拿到query的字符串
// 2. 引用querystring模块,先将query字符串转换成对象,在获取里面的value值
const url=require('url')
const qs=require('querystring')
let str="https://baidu.com/web/1.html?username='dema'&age=22"
let obj=url.parse(str)
let obj2=qs.parse(obj.query)
console.log('username',obj2.username,'age',obj2.age)
//username 'dema' age 22
8.3、fs 文件系统模块
8.3.1、查看是否为文件
-
fs.isFile()
- 返回 ture 或 false
8.3.2、查看是否为目录
-
fs.isDirectory()
- 返回true或false
8.3.3 查看文件状态
-
fs.stat(path,callback)
异步获取-
这个api的获取通过callback,而不是通过返回值
-
path 文件的路径
-
callback 回调函数,用于获取结果
-
err 可能产生的结果
-
result 文件的结果状态
const fs=require('fs') //通过回调函数的第二个参数来打印结果 let res=fs.stat('homework.js',(err,result)=>{ if(err) throw err //抛出代码,组织代码向后运行 console.log(result) // result为局部作用域 })
-
-
fs.statSync(path)
同步获取-
这个api结果的获取直接通过返回值
-
path 文件的路径
const fs=require('fs') let result=fs.statSync('homework.js') console.log(result)
-
8.3.4 创建目录
-
fs.mkdir(path,callback)
异步创建const fs=require('fs') fs.mkdir('mkdir',(err)=>{ if(err) throw err; console.log('目录创建成功') }) // 线程池的 结果放进事件队列 console.log('end') //主程序的 // 执行结果: end 目录创建成功
-
fs.mkdirSync(path)
同步创建const fs=require('fs') fs.mkdirSync('mkdir')//同步也是主程序 consoel.log('end')//主程序 // 执行结果: 先创建文件夹,再输出 end
8.3.5 移除目录
如果目录中有文件要先删除文件
-
fs.rmdir(path,callback)
异步删除const fs=require('fs') fs.rmdir('mydir',(err)=>{ if(err) throw err console.log('移除成功') })
-
fs.rmdirSync(path)
同步删除cosnt fs=require('fs') fs.rmdirSync('mydir')
8.3.6、读取目录
读取到的目录里的文件以数组的形式呈现
-
fs.readdir(path,callback)
异步读取目录const fs=require('fs') fs.readdir('mkdir',(err,result)=>{ if(err) throw err console.log(result) })
-
fs.readdirSync(path)
同步读取目录const fs=require('fs') let result=fs.readdirSync('mkdir') console.log(result)
8.3.7、创建文件并写入
-
fs.writeFile(path,data,callback)
/fs.writeFileSync(path,data)
- 创建文件和写入文件同一个api,因为写入的文件没有就是创建,如果文件有并且有数据,直接清空,然后写入新数据
- path 文件的路径
- data 写入的数据
const fs=require('fs') // 异步创建 fs.writeFile('1.txt','redu.cn',(err)=>{ if(err) throw err console.log('文件写入成功') }) //同步创建 fs.writeFileSync('2.txt','hello')
-
fs.appendFile(path,data,callback)
/fs.appendFileSync(path,data)
- 如果文件不存在,先创建然后写入
- 如果文件存在,在文件的末尾追加写入
const fs=require('fs') //异步创建 fs.appendFile('1.txt','hello',(err)={ if(err) throw err console.log('追击使用成功') }) //同步创建 fs.appendFileSync('2.txt','hello')
-
案例:使用同步创建文件的方法将后台获取的json数据写入文件’student.txt’中
const fs=require('fs') var arr=[ {eid:1,ename:'huwenhao',sex:1} {eid:2,ename:'king',sex:2} {eid:3,ename:'kawb',sex:0} ] for(var val of arr){ let str='序号'+val.eid+'姓名'+val.ename+'性别'+val.sex fs.appendFileSync('student.txt',str) }
8.3.8、读取文件
-
fs.readFile(path,callback)
异步读取 -
fs.readFileSync(path)
同步读取const fs=require('fs') //异步读取 fs.readFile('student.txt','utf-8',(err,data)=>{ if (err) throw err console.log(data) }) //同步读取 let data=fs.readFileSync('3.txt') console.log(data.toString())
8.3.9、删除文件
-
fs.unlink(path,callback)
异步删除 -
fs.unlinkSync(path)
同步删除const fs=require('fs') // 异步删除 fs.unlink('2.txt',(err)=>{ if(err) throw err console.log('删除成功') }) // 同步删除 fs.unlinkSync('2.txt')
8.3.10、检测文件或文件夹是否存在
-
异步已废除,只有同步方法
-
fs.existsSync(path)
返回true和false,可做条件表达式const fs=require('fs') if(fs.existsSync('3.txt')){ fs.unlinkSync('3.txt') console.log('已经被删除') }else{ console.log('3.txt不存在') }
8.3.11、读取流
读取文件的方式,是先把数据存入内存中,然后再从内存中获取数据,如果读取的文件太大,会造成内存压力过大,所以就有了流的操作。分段放入内存,再把数据从内存中取出。
各种类型的数据,例如压缩包,txt,word等
压缩包里不是文本文档,转换为字符串会造成卡死
流读取大型文件,会分成几段读取,所以读取速度快
const fs=require('fs')
// 创建一个可读取的流
let readStream=fs.createReadStream('jj.txt')
// 事件:监听是否有数据流入内存
// data: 事件名称,监听数据的事件
// 通过回调函数来获取数据
let count=0
readStream.on('data',(chunk)=>{
// chunk就是获取的数据,要转成字符串
// console.log(chunk)
// console.log(chunk.toString())
count++ // 当文件大需要分段读取的时候,每度一段加1
})
// 读取结束的事件
readStream.on('end',()=>{
console.log(count)
})
8.3.12、写入的流
把读取的文件放入另一个文件里,最终实现拷贝效果适用于较大文件提高性能
const fs=require('fs')
// 创建可读取的流
let readStream=fs.createReadStream('jj.txt')
// 创建可写入的流
let writeStream=fs.createWriteStream('database.txt')
// 把读取的流通过管道添加到写入流 拷贝
readStream.pipe(writeStream)
8.3.13、普通小文件copy
fs.copyFile(src,dest,callback)
异步拷贝fs.copyFileSync(src,dest)
同步拷贝
// 拷贝小文件 例如微信传递一个文件也是copy的过程
const fs=require('fs')
fs.copyFile('jj.txt','jj2.txt')
8.4、http模块
-
模拟浏览器向另外的服务器发请求
-
http.get(url,callback) 向服务器发请求,通过回调函数获取结果
- url 请求得URL
- callback 回调函数,获取结果
const http=require('http') http.get('www.baidu.com',(res)=>{ res.on('data',(chunk)=>{ consle.log(chunk.toString()) }) })
-
http模块发送get请求
-
导入http模块
var http = require('http');
-
配置请求对象(请求方式,url,请求路径)
var options = { host: 'http://dema.com', port: 10077, method: 'GET', path: '/dema.txt', headers: { 'Content-Type': 'text/plain' } }
-
http.request(地址,响应结果) 发送请求
//发送请求 var req=http.request(options.function(res){ let info="" //通过监听res的data事件,可以得到返回的结果 //返回的结果是一点一点拼接的,不是一次性接收完毕 res.on('data',function(chunk){ info+=chunk.toString() }) //监听data,数据什么时间接收完毕 res.on('end',function(err){ console.log(info) }) }) req.end()
-
-
http模块发送post请求
-
导入http模块
var http = require('http'); //POST多了一个请求参数的处理 var querystring = require('querystring');
-
配置请求对象(请求方式,url,请求路径)
//参数的处理 var data=querystring.stringify({ name:'zhangsan', age:20 }) //请求对象的设置 let options={ host:'www.dema.com', port:10077, method:'POST', path:'/2.txt', headers: { 'Content-Type': 'application/x-www-form-urlencode', //必须在请求头中设置内容的长度 'Content-Length': Buffer.byteLength(data) } }
-
http.request(地址,响应结果) 发送请求
var req = http.request(option, (res) => { let info = '' //post请求返回的结果是一个BUffer类型的数据,需要转化 res.on('data', (chunk) => { info += chunk.toString(); }) res.on('end', (err) => { console.log(info); console.log(err); }) }) req.write(data) //把请求数据放在请求体里面 req.end()
-
-
-
创建web服务器
-
http.createServer()
创建web服务器let app=http.createServer(); app.listen(8080) //监听端口 // 监听浏览器请求,并通过回调函数获取请求,以及做出响应 app.on('request',(req,res)=>{ //res 响应对象 //res.writeHead() 设置响应的状态码和头信息 //res.write() 设置响应的内容 //res.end() 结束并发送响应到客户端 // 返回响应的内容 res.write(' this is my first web') res.end() // 解决中文乱码 res.writeHead(200.,{'Content-Type':'text/html;charset=utf-8'}) res.write('') res.end() // 跳转到另一个url res.writeHead(302,{ Location:'http://baidu.com' }) res.end() //req 请求的对象 //req.url 请求的URL显示端口号后的部分,表示要获取的内容 //req.method 请求的方法 //req.headers请求的头信息 })
-
get传递的数据容易被浏览器缓存(历史记录的url会显示请求的字符串数据)
-
获取get请求的数据 (req.url)
const url=require('url') const qs=require('querystring') var params = qs.parse(url.parse(req.url).query);
-
获取post请求的数据 (req.on())
事件:监听是否有数据传递,通过回调函数来获取数据
req.on('data',(chunk)=>{ // Chunk 就是传递的数据,格式是buffer,转为字符串后为查询字符串,需要解析为对象。 })
-
九、第三方模块
9.1、包(目录模块)和npm
commonJS规范 nodejs往服务器发展的一种规范
nodejs是由多个模块组成,每个模块都有自己独立的作用域,变量和方法。一个模块的变量和方法在其他是不可见的,即使映入其他的模块,在web中也是不可见的,一个模块属于半封闭状态,需要导出后,另一个模块才能引入并看到此模块的方法。require,exports,exportsmodules都是由commonJS提出的。
包:就是一个目录模块
npm: 用于管理包的工具。www.npmjs.com 全局前端放包处,例如:Mysql express koa egg 都是创建web服务器、构建后台的框架。
9.2、搭建第三方模块的使用环境
-
cmd切换到指定目录下,
npm init --y
初始化生成package.json文件(项目包说明文件,会记录项目相关内容及包的信息),不加这个文件,不会下载到该位置 -
npm install express
安装第三方模块,自动生成package-lock.json
文件(记录依赖包的版本号)和node_modules文件夹(第三方模块的包和依赖包)。 -
npm install
自动安装package.json 和 package-lock.json中记录的包以及对应的版本号。
【注】 因为依赖的包太多,node_modules的文件包较大,所有实际工作中,将项目拷贝给别人或者别人将项目拷贝过来,理由并不会有这个文件包,但是会有package.json和package-lock.json文件,执行npm install就会自动安装node_modules的文件。
9.3、express框架
9.3.1、安装
- 终端,cd到指定文件夹下
- 准备文件,
npm init -y
生成文件package.json,不加这个文件,不会下载到该位置 - 安装,
npm install express
,安装好后,会出现package-lock.json文件和node_modules文件夹。该文件下就会出现node_modules文件夹,里面是express的包和附带包。 - 启服务
const express=require('express') //创建web服务器 let app=express() //监听端口 app.listen(8080)
9.3.2、路由
每一个路由处理一个请求,并且都是独立的
app.Method(path,callback)
案例
-
和 http相比,不需要考虑标签和编码问题, 只能用一次send()
// 创建路由:根据请求的URL和方法做出响应 // get 请求的方法 /login请求的url callback做出的响应 app.get('/login',(req,res)=>{ //req请求的对象 //res响应的对象 res.send('<h2>德玛玩前端</h2>')//发送给客户端 })
-
响应发送文件
app.get('/list',(req,res)=>{ //响应文件 res.sendFile(__dirname+'/list.html') })
-
响应发生重定向
app.get('/study',(req,res)=>{ //跳转 res.redirect('http://www.dema.com') })
9.3.3、响应对象和请求对象
-
res 响应的对象
res.send()
设置响应的内容并发送res.sendFile()
响应文件并发送,文件需要使用绝对路径res.redirect()
响应的重定向,跳转到另一个URL- 以上的方法只能执行一次,表示响应已经结束
-
req 请求的对象
req.url
获取请求的urlreq.method
获取请求的方法req.query
获取查询字符串数据,并解析为对象req.params
获取路由传参的数据,格式为对象
9.3.4、获取get请求的数据
-
Get传递的数据容易被浏览器缓存(历史记录的url会显示请求的字符串数据)
-
方式1:字符串传参
// 获取查询字符串数据,并自动解析为对象 cconsole.log(req.query) res.send('注册成功,用户名:'+req.query.uname)
-
方式2:路由传参
// 路由传参 app.get('/pacckage/:pname',(req,res)=>{ //获取路由传参的数据 console.log(req.params.pname) })
9.3.5、获取post请求的数据
-
方式一:同http模块接收方式,用事件监听
-
事件:监听是否有数据传递,通过回调函数来获取数据
req.on('data',(chunk)=>{ // chunk 就是传递的数据,格式是buffer,转为字符串后为 })
-
-
方式二:安装express第三方中间件 body-parser(下方有详细解释)
9.3.6、express中间件
所有中间件的基础语法:app.use() (注:let app=express()
)
浏览器向服务器发请求,中间件可以拦截(过滤)请求,最终给路由提供服务的。
可分为:
- 应用级中间件
- 路由级中间件
- 内置中间件
- 第三方中间件
https://www.expressjs.com.cn/resources/middleware.html
- 错误处理中间件
[注]:Expressjs 从4开始,只保留一个内置中间件,其他都作为第三方中间件使用。
应用级中间件
app.use(url,(req,res,next)=>{})
- url:表示中间件要拦截哪一个路由,对应路由的url,如果为空表示拦截所有的请求
- req res:在中间件中可以获取请求的对象,也可以做出响应
- next是一个函数,表示执行执行下一个中间件和路由
const express=require('express') let app=express() app.listen(8080) // 添加中间件,权限设置 app.use('/list',function(req,res,next){ if(req.query.uname!='root'){ res.send('没有权限') }else{ next() //下一个中间件或路由 } }) // 添加中间件,商品价格打9折 app.use('/shopping',(req,res,next)=>{ console.log(req.query) req.query.price*=0.9 next() }) //list接口 app.get('/list',(req,res)=>{ res.send('允许拿到数据....') }) //shopping接口 app.get('/shopping',(req,res)=>{ res.send('商品价格为'+req.query.price) })
路由级中间件(路由器)
-
主模块使用路由器:
express().use(url,Router)
-
模块中创建路由器:
express.Router()
-
管理各个模块的路由
-
实际开发过程中,web服务器里不会再有路由,所有的路由都由路由器管理
-
有多少功能模块,就有多少路由器
-
实际开发项目中,按功能模块划分:(每一项都是一个路由)
-
用户模块:注册 登录 我的收藏 个人中心 列表
-
商品模块:首页 列表 详情
-
购物车模块:添加 修改 删除
-
内置中间件
-
app.use(express.static('public'))
-
托管静态资源,把所有的静态资源托管到指定的目录,如果浏览请求文件,自动到该目录下寻找,不需要再创建路由响应文件
res.sendFile()
。const express=require('express') const qs=require('querystring') let app=express() app.listen(8080) app.use(express.static('public')) app.post('/myLogin',(req,res)=>{ req.on('data',(chunk)=>{ let obj=qs.parse(chunk.toString()) console.log(obj) }) res.send('登录成功') })
第三方中间件(模块)
1.body-parser 可以转换数据类型
-
安装:
npm install body-parser
-
因为安装express后node_modules已经存在此中间件,所以不需要安装,直接使用
const express=require(express) const bodyParser=require('body-parser') cosnt qs=require('querystring') let app=express() app.listen(8080) //第三方中间件放在路由之前 app.use(bodyParser.urlencoded({ extended:false //false 表示内部解析为对象不使用qs,true表示使用qs模块,内部自动完成不需要手动引入qs模块。 })) // 创建对应的路由 // 接收post请求的参数,取代监听请求数据的方法 app.post('/myLogin',(req,res)=>{ console.log(req.body) console.log(req.body.username) console.log(req.body.password) // req.on('data',(chunk)=>{ // let obj=qs.parse(chunk.toString()) // console.log(obj) // }) })
2.compress 压缩
-
安装
npm install compression
const compression=require('compression') express().use(compression()) // 使用方式1: // 可以用compression中间件压缩和处理静态内容。 // 要在 express.static() 之前使用 app.use(express.static(path.join(__dirname, 'public'))); // 使用方式2: // 在路由之前使用,路由里的文件响应到browser进行了压缩 app.get('/list',(req,res)=>{ res.sendFile(__dirname+'/public/list.html') })
9.4、mysql模块 连接数据库
-
安装
npm install mysql --save
-
引入方式
const mysql=require('mysql')
-
创建方式
mysql.createConnetion()
mysql.createPool()
线程池方式更高效
-
占位符
?
:防止SQL注入,sql语句是用户输入的值 -
执行对数据库的增删改善