Node.JS笔记
Node.JS简介
何为Node.JS
- Node.JS为JavaScript运行时
- Node.JS是JavaScript的运行平台
- 它既不是一门语言,也不是框架,它是一个平台
Node.JS中的JS
- Node.JS没有dom和bom
- EcmaScript
- Node.JS在JavaScript执行环境中为JavaScript提供一些服务器级别的API
- 文件读写
- 网络服务构建
- 网络通信
- http服务器
- ……
Node.JS构建于Chrome的V8引擎
- 代码只是具有特定格式的字符串
- 引擎可以认识它,帮你解析和执行
- Google Chrome的V8引擎是目前公认的解析执行JavaScript代码最快的
- Node.js的作者把Google Chrome中的V8引擎移植出来,开发了一个独立的JavaScript运行时环境
Node.JS的特性
- envent-driven 事件驱动
- non-blocking I/O mode 非阻塞I/O模型(异步)
- ightweight and efficent. 轻量和高效
Node.JS的作用
- web服务器后台
- 命令行工具
- npm(node)
- git(c语言)
- hexo(node)
- …
其它
npm为世界上最大的开源生态系统
初识
安装配置
- 下载:https://nodejs.org/en/
- 安装node环境
- 检测node环境
- 开启命令行提示符(cmd)
- 输入
node --vesion
- 或
node -v
- 正常状态下返回版本号
解析执行JavaScript
- 创建和编写JavaScript脚本文件
- 打开终端(cmd),定位脚本文件所在位置(也就是执行脚本所在文件目录)
- 输入
node 文件名
进行执行
注意:文件名不要使用Node.JS命名,并且最好不用中文
fs
文件操作模块
- 浏览器中的 JavaScript 没有文件操作能力
- Node中的 JavaScript 具有文件操作能力
- fs 是 file-system 的简写,为文件系统的意思
- 在 Node 中如果想要进行文件操作,就必须引入 fs 这个核心模块
- 在 fs 这个核心模块中,就提供了所有文件操作相关的 API,
- fs.readFile 用来读取文件
- fs.writeFile用来写入文件
- 文件中存储的都是二进制数据,用
toString()
方法转换为字符串
读取文件
使用
require
方法加载fs
核心模块使用
readFile
函数读取文件两个参数,第一个为文件路径,第二个为回调函数
回调函数中有两个参数
第一个参数为返回错误,第二个为数据
成功:error: null; data: 返回数据
失败: error: 错误对象; data: undefined
可以利用
error
进行语句判断
1 | //使用node中的fs模块读取文件(使用require语句) |
写入文件
- 使用
require
方法加载fs
核心模块 - 使用
writeFile
函数读取文件- 包含三个参数
- 第一个参数为文件路径及名称
- 第二个参数为写入文本内容
- 第三个参数为回调函数
- 回调函数中的
error
参数
文件写入成功 :error
是null
文件写入失败:error
就是错误对象
1 | var a = require('fs'); |
http
IP地址和端口号
- IP地址用来定位计算机
- 端口号用来定位具体应用程序
- 所有需要联网的应用程序都需要占用一个端口号
- 计算机默认端口号尽量不要访问
- 80
- …
服务器
- 提供服务:为数据服务
- 发请求
- 接收请求
- 处理请求
- 反馈(发送响应)
- 当客户端请求过来,就会自动触发服务器的request请求事件,然后执行第二个参数:回调处理函数
启动服务器
- 加载http模块
- 创建web服务对象
- 监听(注册)request事件
- 绑定端口号,启动服务
1 | //加载http模块 |
request
请求事件处理函数
request
请求事件处理函数,需要接收两个参数:request
和response
request
请求对象:请求对象可以用来获取客户端的一些请求信息,例如请求路径reponse
响应对象:响应对象可以用来给客户端发送响应消息- 响应内容只能是二进制数据或者字符串
- 转出数据内容为其他数据类型时需转化格式
- 一个请求对应一个响应,已经结束响应则无法重复发送响应
- 无请求就无响应
1 | //加载http模块 |
Content-type
- 服务器默认发送的数据为utf8编码内容
- 浏览器在不知道浏览器响应内容编码的情况下,会按当前操作系统默认编码解析
- 中文操作系统默认编码为gbk
- 在 http 协议中,Content-Type 就是用来告知对方我给你发送的数据内容是什么类型
- 不同的资源对应的 Content-Type 是不一样
- Content-Type工具:http://tool.oschina.net/commons
1 | //加载http模块 |
返回文件(http-fs)
发送的并不是文件,本质上来讲发送是文件的内容(一堆字符串)
当浏览器收到服务器响应内容之后,就会根据你的 Content-Type 进行对应的解析处理
结合 fs 发送文件中的数据
字符数据需指定编码
图片不需要指定编码
根据url返回内容
加载指定模块
创建服务对象
监听request事件
- 判断请求的url
- 为对应的url返回文件
- 读取文件内容
- 响应输出文件内容(注意转换格式与编码)
绑定端口号,启动服务
1 | //加载指定模块 |
浏览器输入路径打开文件
需求:用户在浏览器输入文件名即可访问该文件内容
- 将用户输入的文件转化为fs所找文件路径
- fs读取文件
- res响应文件内容
- 输出文件内容
1 | //引用模块 |
重定向
状态码301和302
301
- 永久性的重定向,搜索引擎在抓取新内容的同时将旧网址替换为重定向之后的网址
302
- 暂时性跳转,搜索引擎抓取新的内容的同时保留旧网址
- 服务器返回302时,搜索引擎认为新网址时暂时的
path
路径操作模块
基本操作
- path.basename:获取路径的文件名,默认包含扩展名
- path.dirname:获取路径中的目录部分
- path.extname:获取一个路径中的扩展名部分
- path.parse:把路径转换为对象
- root:根路径
- dir:目录
- base:包含后缀名的文件名
- ext:后缀名
- name:不包含后缀名的文件名
- 🔺path.join:拼接路径(第二个参数会自动判断/是否多余)
- path.isAbsolute:判断一个路径是否为绝对路径
body-parser
简介
body post解析中间件
处理程序之前,在中间件中对传入的请求体进行解析(response body)
处理post请求体
body-parser
提供四种解析器
JSON body parser
Raw body parser
Text body parser
URL-encoded form body parser
安装
1 | npm i body-parser |
引入
1 | var bodyParse = require("body-parse") |
配置
1 | // parse application/x-www-form-urlencoded |
使用
1 | router.post('/login',function(req,res){ |
原生获取post请求体方式
记得先引入querystring
模块
querystring
用作分割请求体内容并转化为对象格式
因为有时候会用到文件上传,所以这里要判断数据请求头的content-type
,如果是multipart/form-data
,则让formidable
中间件去处理,否则自己处理
1 | app.use((req, res, next) => { |
node中的其他成员
__dirname() __filename
- __dirname:动态获取当前模块文件所处目录的绝对路径
- __filename: 动态获取当前文件的绝对路径
在文件操作中,使用相对路径是不可靠的,因为node中文件操作的路径被设计为相对于执行node命令所处的路径。为了解决这个问题,需要使用__dirname()
或 __filename
把相对路径变为绝对路径(绝对路径不受任何影响)。
在拼接路径的过程中,为了避免手动拼接带来的一些错误,就可以使用path.join()
来辅助拼接
1 | var fs = require('fs') |
注意:
模块中的路径标识和文件操作中的相对路径标识不一致
模块中的路径标识就是相对于当前文件模块,不受node命令所处路径影响
node中的模块系统
模块化
何为模块化
- 文件作用域(模块是独立的,在不同的文件使用必须要重新引用)
- 注意: 在node中没有全局作用域,它是文件模块作用域
- 通信规则
- 加载: require
- 导出: exports
模块类型
- 核心模块
- 文件操作的fs
- http服务操作的http
- url路径操作模块
- path路径处理模块
- os操作系统信息
- ……
- 第三方模块
- art-template
- 必须通过npm来下载才可以使用
- 自己写的模块
- 自己创建的文件
模块标识
./
相对于当前路径(在文件操作中可省略)
/
在当前模块所处的磁盘根目录
javascript模块化(需补充)
- Node 中的 CommonJS
- 浏览器中的:
- AMD require.js
- CMD sea.js
- es6中增加了官方支持
CommonJS模块规范
- 模块作用域
- 使用require方法来加载模块
- 使用exports接口对象来导出模板中的成员
加载require
使用require
函数加载模块
若调用非核心模块和第三方模块,必须加上相对路径
./
,可以省略后缀名require
作用- 加载文件模块并执行里面的代码
- 拿到被加载文件模块导出的接口对象
1 | var http = require('http') |
require方法加载规则
- 优先从缓存加载(即不会重复调用同个模块中的函数)
- 避免重复加载,提高模块加载效率
- node会自动寻找当前文件路径的node_modules,从而加载第三方包,若没有,则会继续往上一级目录找,直到找到(如没找到则报错)
main.js
1 | require('./a') |
a.js
1 | console.log('a.js 被加载了') |
b.js
1 | console.log('b.js 被加载了') |
第三方模块加载过程
art-template为例
- 先找到当前项目路径的node_modules
- node-modules/art-template
- node-modules/art-template/package.json
- 找到说明文件中的main属性
- main属性记录art-template的入口模块
- 加载使用这个第三方包
- 实际加载的还是index.js文件
- 若,package.json或main指定的入口模块不存在则node会找该目录下的index.js文件
- 条件均不满足则自动往上一级目录查找
导出exports
使用exports
函数导出需被外部访问的成员
exports
- 在每个文件模块中都提供了一个对象:exports
- exports 默认是一个空对象
- 将需被外部访问的成员挂载到这个 exports 对象中
导出多个成员
方法一
1 | exports.a = 123; |
方法二
1 | module.exports = { |
导出单个成员(这时引用该模块,直接返回hello字符串)
1 | module.exports = 'hello'; |
案例:假设存在a模块和b模块,现在要用a模块访问b模块的成员
a模块:
1 | console.log('hello,i am a'); |
b模块:
1 | // var c = require('./c'); |
c模块
1 | console.log('hello,i am c'); |
结果
module.exports和exports的关系
真正要导出数据是module.exports,而node为了方便我们操作,所以指定了一个变量exports等同于module.exports,,如下代码所示
1 | var exports = module.exports |
所以
1 | exports.a = 2 |
这些值最终会等同于module.exports.a = 2和module.exports.a = 3,同时会被导出
但如果,你这样写代码
1 | exports = 2 |
那么,你相当于改了exports的值,那么它就会与module.exports分道扬镳,它的值也不会等于module导出的值
所以,为了保险起见,新手最好使用module.exports导出你要导出的内容,避免错误
npm
介绍
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
网站
npmjs.com 网站 是用来搜索npm包的
npm命令行工具
npm也有版本概念,可以通过npm --version
来查看npm的版本
升级npm(自己升级自己):
1 | npm install --global npm |
常用命令
npm init(生成package.json说明书文件)
npm init -y(可以跳过向导,快速生成)
npm install
- 一次性把dependencies选项中的依赖项全部安装
- 简写(npm i)
npm install 包名
- 只下载
- 简写(npm i 包名)
npm install –save 包名
- 下载并且保存依赖项(package.json文件中的dependencies选项)
- 简写(npm i 包名)
- –save 自动生成说明说文件信息package.json
- 文件信息自动添加至package.json
- 若删除掉某些项目使用的模块但有保留package.json,则可在命令行(当前项目文件夹下)执行 npm install 全部自动下回来
npm uninstall 包名
- 只删除,如果有依赖项会依然保存
- 简写(npm un 包名)
npm uninstall –save 包名
- 删除的同时也会把依赖信息全部删除
- 简写(npm un 包名)
npm help
- 查看使用帮助
npm 命令 –help
- 查看具体命令的使用帮助(npm uninstall –help)
package.json
每一个项目都要有一个package.json
文件(包描述文件,就像产品的说明书一样)
这个文件可以通过npm init
自动初始化出来
对于目前来讲,最有用的是dependencies
选项,可以用来帮助我们保存第三方包的依赖信息。
如果node_modules
删除了也不用担心,只需要在控制面板中npm install
就会自动把package.json
中的dependencies
中所有的依赖项全部都下载回来。
- 建议每个项目的根目录下都有一个
package.json
文件 - 建议执行
npm install 包名
的时候都加上--save
选项,目的是用来保存依赖信息
package.json和package-lock.json
npm 5以前是不会有package-lock.json
这个文件
npm5以后才加入这个文件
当你安装包的时候,npm都会生成或者更新package-lock.json
这个文件
package.json用处
- 提升下载速度
- npm5以后的版本安装都不要加
--save
参数,它会自动保存依赖信息 - 当你安装包的时候,会自动创建或者更新
package-lock.json
文件,这个文件会包含node_modules
中所有包的信息(版本,下载地址等),这样的话重新npm install
的时候速度就可以提升
- npm5以后的版本安装都不要加
- 锁定版本号
- 从文件来看,有一个lock,称之为锁
- 这个
lock
使用来锁版本的 - 如果项目依赖了
1.1.1
版本 - 如果你重新install其实会下载最新版本,而不是`1.1.1``
- ``package-lock.json`的另外一个作用就是锁定版本号,防止自动升级
Express
案例:express留言板、学生信息增删改
简介
Express 是一个简洁而灵活的 Node.JS Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。
使用 Express 可以快速地搭建一个完整功能的网站。
Express 框架核心特性:
- 可以设置中间件来响应 HTTP 请求。
- 定义了路由表用于执行不同的 HTTP 请求动作。
- 可以通过向模板传递参数来动态渲染 HTML 页面。
安装
1 | npm init //生成说明文件 |
简单使用
- 引包
- 创建服务器应用程序
- 接受请求,返回响应
- 发布服务
1 | //引包 |
art-template
安装
1 | npm install --sava art-template |
配置
1 | app.engine('html', require('express-art-template')) |
使用
1 | res.render('index.html', { |
初识(数据渲染)
1 | var express = require('express') |
express-session
官方文档:https://github.com/expressjs/session
安装
1 | npm i express-session |
配置
- 该插件会为req请求对象添加一个成员:req.session默认是一个对象
1 | //配置session中间件 |
使用
1 | //写 |
其它
session:保存登录选项,🔺在内存中存储
cookie:保存不敏感数据
MongoDB
案例:案例4 学生信息(增删改-mongoose)
关系型和非关系型数据库
关系型数据库
表就是关系,或者说表与表之间存在关系
- 所有的关系型数据库都需要通过
sql
语言来操作 - 所有的关系型数据库在操作之前都需要设计表结构
- 而且数据表还支持约束
- 唯一的
- 主键
- 默认值
- 非空
非关系型数据库
- 非关系型数据库非常的灵活
- 有的关系型数据库就是key-value对
- 但MongDB是长得最像关系型数据库的非关系型数据库
- 数据库 -》 数据库
- 数据表 -》 集合(数组)
- 表记录 -》文档对象
一个数据库中可以有多个数据库,一个数据库中可以有多个集合(数组),一个集合中可以有多个文档(表记录)
1 | //也就是说你可以任意的往里面存数据,没有结构性这么一说 |
安装
下载
🔺环境配置(安装)
node使用(npm)
1 | npm i mongoose |
检测环境
控制台输入mongod --version
启动和关闭数据库
启动数据库服务
1 | mongod --dbpath D:\mongodb\data\db |
关闭服务
1 | 1.在开启服务的控制台,直接Ctrl+C; |
启动数据库,连接本地MongoDB服务
1 | mongo |
退出
1 | exit |
mongo基本命令
show dbs
查看数据库列表(数据库中的所有数据库)
db
查看当前连接的数据库
use 数据库名称
切换到指定的数据库(没有会新建)
show collections
查看当前目录下的数据表
db.表名.find()
查看表中信息
InsertOne()
插入数据(对象形式,命名字符串加双引号)
dropDatabase()
删除数据库
db.collection.remove({})
删除文档
db.collection.drop()
删除集合
🔺Node中操作MongoDB
使用官网mongoDB包操作:
第三方包
mongoose
操作MongoDB数据库官方学习文档
mongoose初识
1 | //引包 |
设计文档结构(表结构)
1 | //引用架构对象 |
数据添加(增)
1 | //添加数据(记录) |
数据删除(删)
1 | Cat.deleteOne({name:'Zild'}, function(err,ret){ |
数据更改(改)
- 根据id
1 | Cat.where({ _id: "5ec9c7012909a22e7c89b5ac" }).update({ name: 'Zild', age: 8 }, function(err, ret) { |
- 根据文档(记录)
1 | Cat.findOneAndUpdate({ name: 'Zild' }, { name: 'Zild1', age: 9 }, function(err, ret) { |
数据查询(查)
查询全部
1 | Cat.find(function(err, ret) { |
查询指定属性的全部对象
1 | Cat.find({ name: 'Zild' }, function(err, ret) { |
查询指定属性的单个对象
1 | Cat.findOne({ name: 'Zild' }, function(err, ret) { |
🔺异步编程
得到函数内部异步操作的结果
回调函数:通过一个函数,获取函数内部的操作。(根据输入得到输出结果)
- 在该情况下无法获得函数内异步操作的结果
1 | function get(a, b) { |
结果:返回undefined
- 若要获得该数据则只能通过回调函数
1 | function get(a, b, c) { |
结果
注意:
凡是需要得到一个函数内部异步操作的结果(setTimeout,readFile,writeFile,ajax,readdir)
这种情况必须通过 回调函数 (异步API都会伴随着一个回调函数)
回调地狱
啥是回调地狱
就是这幅图(图源网络)
为什么会有回调地狱
回调地狱的原因是,当人们试图以一种从上到下的视觉方式执行JavaScript的方式编写JavaScript时。期望第1行发生的任何事情都会在第2行的代码开始运行之前完成,但是,在JavaScript上,有时候这并没办法进行,比如,在你通过异步读取文件时,也就是用fs模块读取多个文件时
1 | var fs = require('fs') |
执行多次后,你会发现,有那么几次,也有可能好几次,看人品吧反正是,它是没有规则的读出来的(往往可能你的文件越大,读出来的时间会更久),也就是说,它并不会按照代码书写顺序去执行,这便是异步编程(如果试了没有,那就一直试,反正总会有的)。异步API导致了代码并不是按顺序执行的(可以读读这篇文章 https://www.jianshu.com/p/39adf6ab8ad1 ——然后嘞,就会有上面那种解决方法,但是你会发现,代码非常的丑(别人是这样说的,反正我不是太这么认为,甚至觉得有点好看),还有非常难维护(这点认同)。所以就出现了几种解决方法 —Promise
Promise
- Promise:承诺,保证
- Promise本身不是异步的,但往往都是内部封装一个异步任务
丢出一张图形容Promise函数,相当于一个容器(下图源于所学教程,pending(悬而未决的))
代码如下,较易维护
1 | var fs = require('fs') |
then函数(ES6)说明:
封装Promise中的readFile
方法
1 | var fs = require('fs') |
Promise应用场景
解决客户端回调嵌套问题
当出现类似于表关联的数据时,这时候就会遇到嵌套问题,当嵌套的数据只有一两个个还好,如果出现三四个甚至五六个,这时候就会出现回调地狱的问题,这里使用promise解决
所需知识:
- npm模块:json-server、http-server
- 客户端模板引擎art-template
- Ajax
- jquery
步骤
安装json-server和http-server以及其他必要模块
1
2
3
4npm i -g http-server
npm i -g json-server
npm i jquery --save
npm i template --save建立html页面
设计表单,人员信息与工作职业相关联,搭配模板字符串使用
1
<form action="" id="user_form"></form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<script type="text/template" id="tpl">
{{ user.username }}">
{{ user.age }}">
{{ each jobs }} {{ if user.job === $value.id }}
{{ $value.id }}" selected>{{ $value.name }}</option>
{{ else }}
{{ $value.id }}">{{ $value.name }}</option>
{{ /if }} {{ /each }}
</script>引用相关模板字符串以及JQuery模块
1
2<script src="node_modules/art-template/lib/template-web.js"></script>
<script src="node_modules/jquery/dist/jquery.js"></script>书写Ajax向服务器发起请求,并封装便于使用
1
2
3
4
5
6
7
8
9function get(url, callback) {
var oReq = new XMLHttpRequest()
oReq.onload = function () {
oReq.responseText
callback(oReq.responseText)
}
oReq.open("get", url, true)
oReq.send()
}开启json-server服务,使用data.json文件(67步使用cmd)
1
json-server data.json
将当前文件所处文件夹开放为服务器
1
http-server
- 若要禁用缓存,则使用以下命令
1
http-server -c-1
若采用回调地狱类型
1
2
3
4
5
6
7
8
9
10get("http://127.0.0.1:3000/users/1",function(userData){
get("http://127.0.0.1:3000/jobs",function(jobsData){
var htmlStr = template("tpl", {
user: JSON.parse(userData),
jobs: JSON.parse(jobsData)
})
console.log(htmlStr)
document.querySelector("#user_form").innerHTML = htmlStr
})
})使用Jquery版的Promise
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//Jquery的Ajax自带promise
var data = {}
$.get("http://127.0.0.1:3000/users/2")
.then(function(user){
data.user = user
return $.get("http://127.0.0.1:3000/jobs")
})
.then(function(jobs){
data.jobs = jobs
// console.log(data)
var str = template("tpl",{
user: data.user,
jobs: data.jobs
})
document.querySelector('#user_form').innerHTML = str
})封装Promise版本的AJAX方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function Rget(url,callback){
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest()
// 当请求加载成功之后要调用指定的函数
xhr.onload = function () {
// 我现在需要得到这里的 xhr.responseText
resolve(JSON.parse(xhr.responseText))
callback && callback(JSON.parse(xhr.responseText))
}
xhr.onerror = function (err){
reject(err)
}
xhr.open("get", url, true)
xhr.send()
})
}- 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14var data = {}
Rget("http://127.0.0.1:3000/users/2")
.then(function(user){
data.user = user
return Rget("http://127.0.0.1:3000/jobs")
})
.then(function(jobs){
data.jobs = jobs
var str = template("tpl", {
user: data.user,
jobs: data.jobs
})
document.querySelector("#user_form").innerHTML = str
})Promise操作数据库
(26-Promise,Promise操作数据库)
- mongoose中所有的API都支持promise
🔺根据查询是否已存在该记录从而决定是否创建新记录
1 | Cat.findOne({ name: "好啊" }) |
注意:
- 每次改完js或html文件后在浏览器需刷新多次
- 每次改完json文件后需要重新启动json-server服务
catch异常处理
在全部then之后添加.catch(err => {})
即可对任何一个then处理过程抛出的异常进行捕获并中止代码继续执行
例如:读取文件并进行后续相关操作,若处理过程发生一个错误则传递给catch,后面所有的then就不再执行
这里要注意区分,如果是在then
中自行处理err
,则代码还是会继续往下执行,这是和catch
不同的点
1 | readFile('a.txt', 'utf8') |
中间件
案例:案例5论坛
中间件的概念
中间件:把很复杂的事情分割成单个,然后依次有条理的执行。就是一个中间处理环节,有输入,有输出。
说的通俗易懂点儿,中间件就是一个(从请求到响应调用的方法)方法。
把数据从请求到响应分步骤来处理,每一个步骤都是一个中间处理环节。
形象化如这个图:自来水厂的净水过程
同一个请求对象所经过的中间件都是同一个请求对象和响应对象。
中间件的分类:
应用程序级别的中间件
万能匹配(不关心任何请求路径和请求方法的中间件):
1 | app.use(function(req,res,next){ |
关心请求路径和请求方法的中间件:
1 | app.use('/a',function(req,res,next){ |
路由级别的中间件
严格匹配请求路径和请求方法的中间件
get:
1 | app.get('/',function(req,res){ |
post:
1 | app.post('/a',function(req,res){ |
put:
1 | app.put('/user',function(req,res){ |
delete:
1 | app.delete('/delete',function(req,res){ |
Express的中间件
在 Express
中,对中间件有几种分类
当请求进来,会从第一个中间件开始进行匹配
- 如果匹配,则进来
如果请求进入中间件之后,没有调用 `next` 则代码会停在当前中间件 如果调用了 `next` 则继续向后找到第一个匹配的中间件
- 如果不匹配,则继续判断匹配下一个中间件
- 如果匹配,则进来
不关心请求路径和请求方法的中间件,也就是说任何请求都会进入这个中间件
中间件本身是一个方法,该方法接收三个参数:
Request
请求对象Response
响应对象next
下一个中间件- 当一个请求进入一个中间件之后,如果不调用 next 则会停留在当前中间件
所以 next 是一个方法,用来调用下一个中间件的
调用 next 方法也是要匹配的(不是调用紧挨着的那个)
错误处理中间件
1 | app.use(function(err,req,res,next){ |
配置使用404中间件:(论坛案例)
1 | app.use(function(req,res){ |
配置全局错误处理中间件: (论坛案例)
1 | app.get('/a', function(req, res, next) { |
内置中间件
- express.static(提供静态文件)
第三方中间件
- body-parser
- compression
- cookie-parser
- mogran
- response-time
- server-static
- session
art-template搭配dateformat模块
简介
art-template搭配dateFormat实现将时间戳格式化为你想要的日期格式
步骤
npm下载对应模块
1
npm i --save dateformat
页面代码(注意art-template默认渲染的页面后缀名为art,time为渲染的时间数据,’yyyy-mm-dd’为你要定义的时间格式)
1
{{ dateFormat(time, 'yyyy-mm-dd')}}
node引用
1
2
3const template = require('art-template');
const path = require('path');
const dateFormat = require('dateformat');配置模板引擎
1
template.defaults.imports.dateFormat = dateFormat;
渲染页面并打出在cmd控制台
1
2
3
4const html = template('06.art', {
time: new Date()
});
console.log(html)其它
nodemon
作用
修改完代码自动重启
安装
1 | npm install --global nodemon |
使用
1 | nodemon 文件 |
ES6函数
find()
方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
实现原理
1 | Array.prototype.findme = function(callback) { |
findIndex()
返回数组中满足提供的测试函数的第一个元素的索引
隐藏元素控件
用来放一些不希望被用户看见,但是需要被提交到服务端的数据
1 | <input type="hidden" name="id" value="{{ student.id }}"> |