个人笔记,Node.js部分 您所在的位置:网站首页 按下tab键切换对象 个人笔记,Node.js部分

个人笔记,Node.js部分

2023-06-03 00:44| 来源: 网络整理| 查看: 265

1.初识Node.js

Node.js是一个基于chrome v8引擎的JS运行环境

Node.js是JS的后端运行环境,无法调用DOM和BOM等浏览器内置api

在node中执行JS代码:

打开终端 → 输入 node 要执行的JS文件路径

切换所处目录命令

(也可以在目录地址栏输入cmd/在目录下shift+右键打开powershell):

cd 需要切换到的路径 //如果要切换到不同盘符,要先输入 盘符:

/终端中的快捷键:

↑键可以快速读取上一次命令

tab键可以快速补全路径

esc键可以清空当前命令

输入cls命令可以清空当前终端

/

2.fs文件系统模块

fs模块是Node官方提供的,用来操作文件的模块

导入fs模块(官方提供,无需额外安装):

const 模块名 = require(‘fs’)

1.读取指定文件内容

语法:

模块名.readFile(‘路径’,[编码格式],回调函数)

回调函数有两个固定形参,err(失败的结果)和dataStr(成功所拿到的文本) //可改名

如果读取成功,err默认是null

如果读取失败,则err的值为错误对象,dataStr的值为undefined

2.指定文件写入内容

语法:

模块名.writeFile(‘路径’,‘内容’[,编码格式,默认utf8],回调函数)

回调函数有一个固定形参,err(失败的结果)//可修改名字

文件写入成功,err的值为null

文件写入失败,err的值为错误对象

注意:原有的内容会被覆盖,可以生成没有的文件,不能生成没有的路径

3.fs模块动态拼接路径问题

如果使用相对路径,代码在运行时,会执行node命令时所处的目录来动态拼接操作文件的路径,如果不在文件原本路径运行node,会产生报错

如果使用完整的路径防止问题发生,但会造成移植性差,不利于维护的问题

因此,在node中一般使用__dirname(当前文件所属目录)

例如:__dirname+‘/files/txt/1.txt’

3.path路径模块

path模块是官方提供的用来处理路径的模块

导入path模块(官方提供,无需额外安装):

const 模块名 = require(‘path’)

1.路径拼接

语法:

path.join(路径1,路径2,……)

注意…/在语法中会抵消前一个路径的最深层

对于__dirname的使用一般也使用path.join语法

2.获取路径中的文件名

语法:

path.basename(‘路径’,[文件扩展名])

返回路径中的最后一部分字符串

输入扩展名可以自动清除扩展名部分,只留文件名

3.获取路径中的文件扩展名

语法:

path.extname(‘路径’)

返回扩展名字符串

4.http模块

http模块是node官方提供的,用来创建web服务器的模块

导入http模块(官方提供,无需额外安装):

const 模块名 = require(‘http’)

1.服务器相关概念

IP地址是互联网上每台计算机的唯一地址,类似于电话号码,ip地址的常见格式是a.b.c.d,每一部分都是0-255之间的十进制整数,互联网中的每台web服务器都有其独立的ip地址

域名与ip地址是一一对应的关系,这份关系存放在域名服务器中,使用者只需记忆域名即可访问对应的服务器

在一台电脑中可以运行很多web服务,每个web服务都对应着唯一的端口号,客户端发送过来的网络请求,通过端口号,可以准确地交给对应的web服务处理,实际运用中,80端口可以被省略

2.创建web服务器

在导入http模块后,创建web服务器实例:

const 服务器实例 = 模块名.createServer()

为服务器实例绑定request事件:

服务器实例.on(‘request’,(req,res)=>{

回调函数体

})

启动服务器:

服务器实例.listen(端口号,回调函数)

req请求对象:访问客户端相关的数据或属性

主要的属性和方法有:

req.url:客户端请求的url地址,从端口号后开始

req.method:客户端请求的类型,例如get,post

res响应对象:访问服务器相关的数据或属性

主要的属性和方法有:

res.end(内容):返回内容且结束访问,类比return

注意res.end返回中文时浏览器会显示乱码,要设置响应头:

res.setHeader(‘Content-Type’, ‘text/plain;charset=utf-8’);

text/plain无法识别标签,如果需要识别标签可以改为text/html

5.模块化

模块化是解决一个复杂问题时,自顶向下逐层把系统划分成若干个模块的过程,对于整个系统而言,模块是可以组合,分解和更换的单元

代码模块化可以提高代码的复用性和可维护性,可以实现按需加载

1.Node.js中的模块

Node中模块分为三大类,分别是:

内置模块:官方提供的模块,例如fs,path,http等。加载写名字即可

自定义模块:用户创建的js文件都是自定义模块。加载需要路径

第三方模块:第三方提供的模块,需要下载使用。加载写名字即可

实际开发中,使用require()方法可以自由加载模块,加载时会执行模块内的代码

Node中也有类似于函数作用域的模块作用域,在自定义模块中定义的变量,方法等,只能在当前模块内访问,防止了全局变量污染

2.module对象

module对象中储存了当前模块有关的信息

在自定义模块中,可以使用module.exports对象将内部成员共享出去,在外界使用require接收时,得到的就是module.exports对象中的内容

在默认情况下,Node还提供了exports对象简化操作,但如果module.exports改变了指向的对象,exports对象不会改变,最后共享的结果还是以module.exports对象为准

3.Node中的模块化规范

1.每个模块内部,moudle变量代表当前模块

2.module变量是一个对象,module.exports是对外的接口

3.require()方法用于加载模块

6.npm与包

Node中,第三方模块又称为包,Node中的包都是免费且开源的,供第三方免费下载使用

包是基于内置模块封装出来的,提供了更高级,更方便的api,提高开发效率

www.npmjs.com 是全球最大的包共享平台,可以在其中搜索包

registry.npmjs.org 使用包管理工具,用来下载所需的包

要安装包,需要在终端中使用命令:

npm i 完整的包名称

如果需要安装指定版本的包:

npm i 完整的包名称@版本号

包的版本号代表着(前面的版本号增长,后面归0):大版本.功能版本.bug修复版本

项目根目录中,又一个叫做package.json的包管理配置文件,记录一些例如项目名称,版本号,项目描述,所用的包,开发用到的包,开发和部署都用到的包等等

在多人协作的时候,第三方包的体积过大,因此要剔除node_modules目录(使用.gitignore),使用package.json记录安装的包,让合作者自行下载包

快速创建包管理配置文件:

npm init -y

上述命令只能在英文目录下运行,不能使用中文,不能包含空格(当前目录即可)

用npm install命令时会自动写入包的信息在dependencies节点中

自动安装包管理配置文件里的包:

npm install(或者i)

即可直接一次安装所有记录的包

卸载包(会从配置文件内移除):

npm uninstall 包名

当一个包只在项目开发阶段会用到,可以把这些包记录到devDependencies中

npm i 包名 -D

下包速度慢解决:

使用淘宝npm镜像服务器:

检查当前下包源:

npm config get registry

下包源切换成淘宝npm镜像服务器:

npm config set registry=https://registry.npm.taobao.org

检查是否下载成功:

npm config get registry

还可以使用nrm快速切换:

安装nrm:

npm i nrm -g

查看可用镜像源:

nrm ls

切换镜像源:

nrm use 服务器简称

1.包的分类

项目包:

安装到node_modules目录的包都是项目包

分别有开发依赖包(开发时才用得到)和核心依赖包(开发和上线后都用得到)

全局包:

当安装时添加 -g 参数,则会把包安装为全局包

全局包安装到C:\Users\用户目录\AppData\Roaming\npm\node_ modules目录下

卸载也需要添加-g参数

2.i5ting_toc包

可以把md文档转化为html页面

使用语法:

i5ting_toc -f 需要转换的md文件路径 -o

3.发布包:

创建好包的根目录后要创建三个文件:

package.json(包管理配置文件):

“nane”:“包名”

“version”:“版本号”

“main”:“入口文件”

“description”:“简要描述包的作用”

“keywords”:[“检索词1”,“检索词2”,“检索词3”]

“license”:“ISC” //开源协议

index.js(包的入口文件)

README.md(包的说明文档):

安装方式,导入方式,功能,开源协议

在终端中登录npm:

npm login 用户名 密码(输入不显示) 邮箱

注意:发布包之前要切换到官方服务器,包名不能与他人相同

在切换到包的根目录后,运行:

npm public

删除已发布的包(只能在72小时之内删除,24小时内不能重复发布):

npm unpublish 包名 --force

4.模块的加载机制

模块在加载一次后会被缓存,多次调用会优先在缓存中加载,提高加载效率

内置模块的加载优先级最高,当有其他包重复名称时,require加载的永远是内置模块

加载自定义模块时,一定要使用./或…/这样的路径标识符进行加载,否则node会将其认为是内置模块或第三方模块加载

在加载自定义模块未输入扩展名时,node会自动按以下顺序加载文件:

按原文件名加载→按照.js加载→按照.json加载→按照.node加载→终端报错

在加载第三方模块时,node会从其同级node_modules目录下搜索,若未找到,会依次向上级目录node_modules目录下查找

7.express

express是第三方的,类似http模块的web服务器创建平台,可以更便捷的创建服务器

1.用express创建服务器

在导入express后,创建服务器:

const 服务器名 = express()

启动服务器:

服务器名.listen(端口号,回调函数)

2.用express监听get/post请求

监听get请求:

服务器名.get(‘请求url’,回调函数(有req和res两个形参))

监听post请求:

服务器名.post(‘请求url’,回调函数(有req和res两个形参))

express提供了更多req和res操作:

res.send(内容):发送内容,如果是对象会转为JSON格式

req.query:客户端发送的查询字符串(例如:?name=zs),默认情况下是空对象

req.params:匹配:后的动态参数,默认情况下是空对象(例如:/user/:id在客户端发送/user/1时,req.params里的id:1),动态参数可以是多个

3.托管静态资源

创建静态资源服务器:

服务器名.use(express.static(‘静态资源目录’))

之后就可以访问静态资源目录中的所有文件,存放静态资源的根目录名不会出现在url中

如果需要托管多个,只需要多次调用express.static()函数即可,访问时,会根据目录的添加顺序查找所需的文件

挂载路径前缀:

express.static(‘/路径前缀’,‘静态资源目录’)

最后访问时会变成:url地址/路径前缀/静态资源

4.nodemon

nodemon工具可以在修改项目文件代码后,自动重启项目,极大地方便了开发和调试

在启动项目时,只需把node替换为nodemon即可:

nodemon 项目名

5.路由

路由就是映射关系,在express中,路由由请求的类型,url地址和处理函数组成:

服务器名.请求类型(‘请求的url地址’,处理函数(有req和res两个形参))

为了对路由进行模块化的管理,express不建议将路由直接挂载在服务器上,而是推荐将路由抽离为单独的模块:

创建路由模块对应的js文件

然后使用express.Router()函数创建路由对象:

路由对象.请求类型(‘请求的url地址’,处理函数(有req和res两个形参))

向路由对象是挂载具体的路由,随后使用module.exports向外共享路由对象

最后在主文件中导入模块且注册路由模块:

服务器名.use(路由对象)

路由模块也可以添加前缀:

服务器名.use(‘/前缀地址’,路由对象)

6.中间件

中间件特指业务流程中的中间处理环节,Node中按照书写顺序调用,一定要写在路由前

中间件在实际开发中,多个中间件共享同一个req和res,我们可以在上游的中间件中统一在req或res对象添加自定义的属性或方法,供下游的中间件或路由使用(组件化)

express中间件本质上就是一个处理函数,格式如下:

服务器名.请求类型(‘请求的url函数’,处理函数(有req,res和next三个参数))

next参数的作用:

next参数本质上是一个函数,是实现多个中间件连续调用的关键

调用next()就是把流转关系交给下一个中间件或者路由处理,一定要调用

全局中间件:

客户端发起任何请求(任何请求类型和页面都会触发)都会触发的中间件,格式如下:

服务器名.use(全局中间件函数)

局部中间件:

服务器名.请求类型(‘请求的url函数’,中间件函数1,中间件函数2,……,处理函数(有req和res两个参数))

1.中间件的分类

express官方把中间件分为了五大类:

①应用级别的中间件

通过服务器.use()/服务器get()/服务器.post()绑定到服务器实例上的中间件都称为应用级别的中间件

②路由级别的中间件

绑定到express.Router()上的中间件成为路由级别的中间件

③错误级别的中间件(防止程序完全崩溃,正常执行错误中间件)

专门捕获项目中的一场错误,防止项目异常崩溃的问题,必须按顺序包括四个形参:err,req,res,next

其中err.message是错误相关的内容

必须注册在所有路由之后

④express内置中间件

express内置了三个常见中间件:

express.static() //快速托管静态资源内置中间件

express.json()//解析json格式的请求体请求

express.urlencoded()//解析url-encoded格式的请求体数据

使用方式:

如果客户端发送的是类似JSON格式的请求体数据,使用

req.body接收,如果没有配置解析表单的中间件,默认等于undefined

在这里插入图片描述 ⑤第三方中间件

非内置的,第三方提供的中间件

7.跨域

使用CORS完成接口跨域,CORS是express第三方中间件,由一系列http响应头组成,这些响应头决定浏览器是否阻止前端js代码跨域获取资源,使用方式:

使用npm i cors安装

在路由之前配置cors:

const cors = require(‘cors’)

全局注册cors:

服务器名.use(cors())

注意cors有兼容性问题,在ie9之前的浏览器无法正常使用

在这里插入图片描述 默认情况下cors仅支持客户端发起GET,POST,HEAD请求

如果需要支持其他请求,需要配置:

res.setHeader(‘Access-Control-Allow-Methods’,‘允许的请求方式1,方式2……’)

如果允许所有的请求,则直接填入*

1.CORS的请求分类

①简单请求:

如果请求方式属于GET,POST和HEAD三者之一,并且http头部信息不超过默认规定的范围内。

客户端与服务器只会发生一次请求

②预检请求:

请求方式属于默认以外的方式,或者包含自定义头部字段,或者发送了application/JSON格式的数据

预检请求就是,在正式通信前,浏览器会先发送option请求进行预检,如果服务器允许且成功响应,才会发送真正的请求,并携带真实数据

客户端和服务器会发起两次请求

2.jsonp接口编写

浏览器端通过

JSONP只支持GET请求,不属于真正的Ajax请求,因为没有使用XHR对象

JSONP的接口一定要写在CORS中间件前

格式:

服务器名.get(‘请求的url’,(req,res) =>{

//首先获取客户端发送的回调函数的名字

const 回调函数名 = req.query.callback

//定义要通过JSONP返回的数据

const 数据名 = {数据}

//将数据和函数名拼接成字符串

const 字符串名 = ${回调函数名}(${JSON.stringify(数据名)})

//发送回客户端

res.send(字符串名)

})

8.数据库

数据库是用来组织,存储和管理数据的仓库

常见的数据库有很多种,常见的有:

MySQL,Oracle(收费),SqlServer(收费),MongoDB(免费or收费)

前三个数据库属于传统型数据库,设计理念相同,用法比较类似

MongoDB是新型数据库,在一定程度上弥补了传统数据库的缺陷但不是替代关系

其中MySQL是开源免费(有收费版)的数据库,使用广泛,流行度高

传统型数据库的数据组织结构,类似于Excel中的数据组织结构

Excel中:工作簿包含工作表包含数据行和列

传统型数据库中:数据库包含数据表包含数据行和字段

一般情况下,每个项目对应着独立的数据库,不同的数据要储存到数据库的不同的表中,例如:图书存在books,用户储存到users

表中储存哪些信息由字段决定,例如:user表有ID,username,password字段

1.MySQL

对开发人员来说,只需要MySQL server和MySQL workbench两个软件即可

MySQL server用来提供数据储存和服务,MySQL workbench用来可视化管理MySQL

正确安装MySQL后,进入数据库,选择上方从左往右第四个工具创建新的数据库,name不能包含中文和空格,空格尽量使用_替代

创建数据表:

在数据库中右键tables节点,选择create,输入name(表名),comments(注释可选),column(字段)

datatype分类:

int — 整数

varchar(最大长度) — 字符串

tinyint(1) — 布尔值

字段特殊标识,从左往右:

PK — 主键(唯一标识)

NN — 非空

UQ — 值唯一

bin —二进制数据

AI — 值自动递增

zf — 自动填充0

g — 生成列

写入数据:

在创建的表上右键,选择select rows - limit1000

2.SQL

sql是专门用来访问和处理数据库的编程语言,可以让我们以代码的形式,操作数据库里的数据,只能在传统型数据库中使用,语句对大小写不敏感

sql可以增删改查数据库的数据,还可以创建新数据库,表等等

在sql中 --表示注释

1.select语句

用于从表中查询数据,格式:

SELECT 列名称1,列名称2 FROM 表名称

全部查询在列名称填入*

2.insert语句

用于在表中插入数据

插入数据行,语句:

insert into 表名(列1,列2,……) values(值1,值2)

3.update语句

用于在表中更新数据,语法:

update 表名 set 列名1=新数据1,列名2,新数据2 where 筛选项(例如:id=1)

4.delete语句

用于在表中删除数据,语法:

delete form 表名称 where 筛选项

5.where子句

用于限定选择的标准,在select,update,delete语句中都可以使用

可以在where子句中使用的运算符:

=(等于)和(不等于,也可以写成!=)

=(大于和大于等于)

between(在某个范围内)

like(某种搜索模式)

6.and和or运算符

and和or运算符可以在where子句中把两个或多个条件结合起来

例如:delete from users where id=1 and/or status=1

and相当于js中的&&(与)运算符,or相当于js中的||(或)运算符

7.order by语句

根据指定的列对结果进行排序,默认按照从小到大(asc)排列

如果要修改为从大到小,需要使用DESC关键字

例如:select * from users order by status desc

如果需要多重排序:

select * from users order by status desc,username asc

(先按照status降序排序,再按照username字母顺序升序排序)

8.count(*)函数

用于返回查询结果的总条数:

**select***count()**form users where status = 0

9.as关键字

为查询出来的列设定别名

select count(*)AS 别名from users where status=0

3.在Node中使用mysql

使用npm i mysql进行安装模块

引入:const mysql = require(‘mysql’)

配置:const 数据库名 = mysql.createPool({

host:‘数据库ip地址’

user:‘数据库账号’

password:‘密码’

database:‘指定操作的数据库名’

})

执行sql语句:

数据库名.query(‘sql语句’,回调函数(有err(错误信息)和results(返回结果)两个形参))

使用node筛选数据,得到的是数据为对象的数组

使用node插入数据,可以在sql语句中使用占位符?,之后用数组赋值,例如:

数据库.query(insert into users(username,password) values**(?,?),[‘用户名’,‘密码’]****,回调函数)**

这样可以方便通过客户提交的数据导入数据库

当results.affectedRows = 1时,插入数据成功

便捷插入数据:

如果数据对象的每个属性与数据表的字段一一对应,则可以通过以下方式快速插入

例如:

const user = {username:‘zs’,password:‘123456’}

const sqlStr = ‘insert into users set**?****’**

数据库.query(sqlStr,user,回调函数)

使用node更新数据:

与创建类似,update也可以使用占位符:

数据库.query{‘update users set username=?,password=?where id=?’[user.username,user.password,user.id],回调函数}

当results.affectedRows = 1时,更新数据成功

更新数据的便捷方式也和插入类似:

sql语句:update users set**?where id=?**

要求导入的对象和数据表字段一一对应

使用node删除数据:

在删除数据时,尽量使用id这样的唯一性标识来删除对应的数据:

数据库.query(‘delete from users where id = ?’,user.id,回调函数)

标记删除:

为了保证用户不是误触删除,推荐使用标记删除的形式来模拟删除操作,模拟删除就是类似于status这样的字段,在用户点击删除时,使用update来标记用户删除的数据

9.session认证

http的每次请求都是独立的,如果连续多次发生请求,服务器不会保留每次的状态,因此要通过cookie记录用户状态

cookie是储存在用户浏览器中一段不超过4kb的字符串,由一个名称,一个值,和其他几个用于控制cookie有效期,安全性,适用范围的可选属性组成

不同域名下的cookie是独立的,在发起请求时,浏览器会自动发送对应域名下的未过期的cookie

客户端第一次请求服务器的时候,服务器通过响应头的方式向客户端发送一个身份认证的cookie,之后当浏览器每次请求服务器的时候,浏览器会自动将身份认证相关的cookie通过请求头的方式发送给服务器

cookie不具有安全性,cookie储存在浏览器中,且浏览器提供了读写cookie的api,因此隐私数据不应该通过cookie传输。

1.session认证机制

大多数时候用于非跨域解决方案,用户的信息保存在服务器端

在npm中安装express-session中间件

let session = require(‘express-session’)

服务器名.use(session({

secret:‘描述’,

resave:false, //固定写法

saverUninitialized:true //固定写法

}))

在session中存/取数据:

req.session来访问和使用session对象

例如:req.session.user = req.body.username

if(!req.session.islogin){}

清空session(例如用户退出登录):

req.session.destroy

2.jwt认证机制

session的认证机制需要配合cookie才能实现,但cookie默认不支持跨域访问,因此需要做很多额外的配置,才能实现session跨域,因此jwt认证机制出现了

jwt是最热门的跨域认证机制

jwt的储存方式是将用户的信息通过token字符串的形式储存在客户端浏览器(localstorage或sessionstorage)中,服务器通过还原token字符串的形式来认证用户身份

jwt由三部分组成:头部(header).有效荷载(payload).签名(signature)

在其中,payload才是真正的加密后的用户信息,而header和signature是安全性相关的部分

jwt使用:

当客户端收到服务器返回的jwt后,上传推荐的做法是吧jwt放在http请求头的Authorization中:

Authorization:Bearer

使用jwt:

使用jsonwebtoken(生成字符串)和express-jwt(解析字符串)两个包

使用require分别导入

为了保证安全性,我们要定义secret秘钥加密jwt字符串:

const secretKey = ‘任意字符串’

生成jwt字符串:

jwt.sign({用户信息对象},secretKey,{expiresIn(有效期):‘60s’})

第三部分又称为配置对象

还原jwt:

服务器可以通过express-jwt来自动解析token,转换成json对象

express-jwt最新版本需要配置algorithms算法,一般默认是HS256,配置格式

服务器名.use(jwt中间件.expressjwt{secret:secretKey,algorithms: [‘HS256’]}).unless({path:[不需要访问权限的接口]})

配置成功后,就可以使用req.auth来访问从jwt字符串解析出来的用户信息:

在用户的密码加密:

导入bcryptjs包,调用bcrypt.hashSync(明文密码,随机盐的长度)

用户的密码验证:

使用if,else校验复杂难懂,因此引入第三方joi包让校验更加方便

使用npm i joi安装包



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有