Node.js

Node.js是一个基于Chrome V8引擎的Java Script运行环境。

一、初识Node.js

  • 环境的安装

  • 执行js代码

    • 在终端中执行:node 要执行的js文件路径
      node E:\projects\my_test\test.js

二、fs模块

fs 模块是Node.js 官方提供的、用来操作文件的模块。

  • 读取文件

    • readFile(异步读取)
      • 语法
        fs.readFile(path[, options], callback)
      • 参数
        • 参数1:必选参数,字符串,表示文件的路径
        • 参数2:可选参数,表示什么编码格式来读取文件,一般默认指定utf8
        • 参数3:必选参数,文件读取完成后,通过回调函数拿到文件读取的结果
          • 回调函数参数:
            • 参数1:err,读取成功,err为null,否则返回错误对象,可以通过err.message获取失败信息
            • 参数2:dataStr,成功读取的文件内容
      • 示例
        // 1、导入fs模块
        const fs = require('fs')
        
        // 2、调用fs.readFile()方法异步读取文件
        fs.readFile('./test.txt', {encoding: 'utf8'}, (err, dataStr) => {
            //2.1 打印失败的结果
            if(err){
                return console.log('读取文件错误'+err.message)
            }
            //2.2 打印成功读取的结果
            console.log('文件读取成功,内容:'+dataStr)
        })
    • readFileSync(同步读取)
      • 语法
        fs.readFileSync(path[, options])
      • 参数
        • 参数1:必选参数,字符串,表示文件的路径
        • 参数2:可选参数,表示什么编码格式来读取文件,一般默认指定utf8
      • 返回值
        • 读取的文件内容
      • 示例
        // 1、导入fs模块
        const fs = require('fs')
        
        // 2、调用readFileSync()方法,同步读取文件,并返回文件内容
        data = fs.readFileSync('test.txt', 'utf8')
        console.log('同步读取:' + data)
  • 写入文件

    • writeFile(异步写入
      • 语法
        fs.writeFile(file, data[, options], callback)
      • 参数
        • 参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径
        • 参数2:必选参数,表示要写入文件的内容
        • 参数3:可选参数,表示以什么格式写入文件内容,默认值utf8
        • 参数4:必选参数,文件写入完成后的回调函数
      • 示例
        // 1、导入fs模块
        const fs = require('fs')
        
        // 2、调用fs.writeFile()方法写入文件
        fs.writeFile('./test.txt', '通过writeFile方法写入的内容', (err) => {
            //2.1 打印失败的结果
            if(err){
                return console.log('写入文件错误'+err.message)
            }
            //2.2 打印成功的结果
            console.log('文件写入成功')
        })
    • writeFileSync(同步写入)
      • 语法
        fs.writeFileSync(filename, data[, options])
  • 路径动态拼接的问题

    • 在使用fs模块操作文件时,如果使用 ./ 或者 ../ 开头的相对路径时,很容易会出现路径拼接错误的问题
      • 原因:代码在运行的时候,会以执行 node 命令时所处的目录,动态拼接出被操作文件的完整路径
    • 解决方案:
      • 使用__dirname来拼接出完整路径
      • __dirname:表示当前文件所处的目录

三、path路径模块

path 模块是 Node.js 官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理需求。

  • path.join([...paths])

    • 路径拼接
    • 参数:
      • ...paths:路径片段的序列,字符串类型
  • path.basename(path[, ext])

    • 获取路径中的文件名
    • 参数:
      • path:必选参数,表示一个路径的字符串
      • ext:可选参数,表示文件扩展名
  • path.extname(path)

    • 获取路径中的文件扩展名部分
    • 参数:
      • path:必选参数,表示一个路径的字符串
  • 示例

    const path = require('path')
    
    // 注意../会抵消前面的一层路径
    fullPath = path.join('/a','b','../','c/index.html')
    console.log(fullPath) // a\c\index.html
    
    const fullName = path.basename(fullPath)
    console.log(fullName) // 输出 index.html
    
    const nameWithoutExt = path.basename(fullPath,'.html')
    console.log(nameWithoutExt) // 输出 index
    
    const extName = path.extname(fullPath)
    console.log(extName) // 输出 .html

四、http模块

http 模块是 Node.js 官方提供的、用来创建 web 服务器的模块。

  • 创建基本的web服务器

    const http = require('http')
    
    // 创建 web 服务器实例
    const server = http.createServer()
    
    // 为服务器实例绑定 request 事件,监听客户端的请求
    server.on('request', function (req, res) {
      const url = req.url
      const method = req.method
      const str = `Your request url is ${url}, and request method is ${method}`
      console.log(str)
    
      // 设置 Content-Type 响应头,解决中文乱码的问题
      res.setHeader('Content-Type', 'text/html; charset=utf-8')
      // 向客户端响应内容
      res.end(str)
    })
    
    server.listen(8080, function () {
      console.log('server running at http://127.0.0.1:8080')
    })
  • 根据不同的url响应不同的内容

    const http = require('http')
    const server = http.createServer()
    
    server.on('request', (req, res) => {
      // 1.获取请求的url
      const url = req.url
      // 2.设置默认的响应内容为 404 Not found
      let content = '<h1>404 Not found!</h1>'
      // 3.判断用户请求的是否为 / 或 /index.html 首页
      // 4.判断用户请求的是否为 /about.html 关于页面
      if (url === '/' || url === '/index.html') {
        content = '<h1>首页</h1>'
      } else if (url === '/about.html') {
        content = '<h1>关于页面</h1>'
      }
      // 5.设置Content-Type响应头,防止中文乱码
      res.setHeader('Content-Type', 'text/html; charset=utf-8')
      // 6.使用res.end()把内容响应给客户端
      res.end(content)
    })
    
    server.listen(80, () => {
      console.log('server running at http://127.0.0.1')
    })

五、模块化

  • 模块化的基本概念

    • 模块化是指解决一个复杂问题时,自顶向下逐层把系统划分为若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。
    • 编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块。
    • 模块化可以提高代码的复用性、可维护性,可以实现按需加载。
  • 模块的分类

    • Node.js中根据模块来源的不同,将模块分为了3大类,分别是:
      • 内置模块(由Node.js官方提供,例如fs、path、http等)
      • 自定义模块(用户创建的每个js文件)
      • 第三方模块(由第三方开发,使用前需要先下载)
  • 加载模块

    • 使用强大的require()方法
      // 1.加载内置的http模块
      const http = require('http')
      
      // 2.加载用户自定义模块
      const myUtils = require('./myUtils.js')
      
      // 3.加载第三方模块(需要先下载)
      const moment = require('moment')

      注意:使用require()方法加载模块时,会执行被加载模块中的代码

  • 模块作用域

    • 和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域
    • 好处:
      • 防止了全局变量污染的问题
  • 向外共享模块作用域中的成员

    • module对象
      • 在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息
    • module.exports对象
      • 在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用
      • 外界使用require()方法导入自定义模块时,得到的就是module.exports所指向的对象
      • 默认情况下,module.exports = {}
    • exports对象:
      • 默认情况下,exports和module.exports指向同一个对象。最终共享的结果,还是以module.exports指向的对象为准
  • 模块化规范

    • Node.js遵循了CommonJS模块化规范,CommonJS规定了模块的特性和各模块之间如何相互依赖
    • CommonJS规定:
      • 每个模块内部,module 变量代表当前模块
      • moudle 变量是一个对象,它的exports属性(即module.exports 是对外的接口
      • 加载某个模块,其实是加载该模块的module.exports 属性。require()方法用于加载模块
  • 模块的加载机制

    • 优先从缓存中加载
      • 模块在第一次加载后会被缓存。这也意味着多次调用require()不会导致模块的代码被执行多次,从而提高模块的加载效率
    • 内置模块的加载机制
      • 内置模块的加载优先级最高
        • 例如,加载fs模块时,即使node_modules目录下有同名的包,也会返回内置的fs模块
    • 自定义模块的加载机制
      • 必须指定以 ./ 或 ../ 开头的路径标识符,否则会当作内置模块或第三方模块进行加载
      • 在使用require()导入自定义模块时,如果省略了文件的扩展名,则Node.js会尝试按照顺序加载以下的文件:
        • 按照确切的文件名进行加载
        • 补全.js扩展名进行加载
        • 补全.json扩展名进行加载
        • 补全.node扩展名进行加载
        • 加载失败,终端报错
    • 第三方模块的加载机制
      • 如果传递给require()的模块标识符不是一个内置模块,也不是以 ./ 或 ../ 开头,则Node.js会从当前模块的父目录开始,尝试从/node_modules文件夹中加载第三方模块。
      • 如果没有找到对应的第三方模块,则去上一层父目录中进行加载,直到文件系统的根目录
      • 例如,假设在 C:\Users\bruce\project\foo.js 文件里调用了 require('tools'),则 Node.js 会按以下顺序查找:
        • C:\Users\bruce\project\node_modules\tools
        • C:\Users\bruce\node_modules\tools
        • C:\Users\node_modules\tools
        • C:\node_modules\tools
        • 报错
    • 目录作为模块
      • 当把目录作为模块标识符,传递给require()进行加载的时候,有三种加载方式:
        • 在被加载的目录下查找一个叫做package.json的文件,并寻找main属性,作为require()加载的入口
        • 如果目录里没有package.json文件,或者main入口不存在或无法解析,则Node.js将会试图加载目录下的index.js文件
        • 以上均失败,则终端报错

六、npm与包

    • Node.js中的第三方模块又叫做包
    • 不同于内置模块和自定义模块,包是由第三方个人或团队开发出来的,免费供所有人使用。
    • 包是基于内置模块封装出来的,提供了更高级、更方便的API,极大的提高了开发效率
    • 搜索包网站:https://www.npmjs.com/
    • 下载包地址:https://registry.npmjs.org/
  • npm

    • Node Package Manager(简称npm包管理工具),随着Node.js的安装包一起安装到用户电脑上,使用这个包管理工具,可以从https://registry.npmjs.org/服务器将需要的包下载到本地使用
    • 终端执行 npm -v 命令,可以查看npm包管理工具的版本号
      npm -v
    • 初次安装包以后多了哪些文件?
      • node_modules文件夹:用来存放所有已安装到项目中的包。require()导入第三方包时,就是从这个目录中查找并加载包
      • package-lock.json配置文件:用来记录node_modules目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等
      • 注意:
        • 上述文件夹和文件中的内容我们不需要手动维护,由npm自动维护
    • 安装包
      • npm install 包名
        • 也可简写为:npm i 包名
      • npm install 包@版本号
        • 指定版本安装
          npm install moment@2.29.4

          第1位数字2表示大版本,第2位数字29表示功能版本,第3位数字4表示Bug修复版本,只要前面的版本号增长了,后面的版本号就需要归零

    • 包管理配置文件
      • 在项目根目录中,必须提供一个叫做package.json的包管理配置文件,即可用来记录项目中安装了哪些包。
      • 多人协作开发时,为了避免第三方包的体积过大,在团队成员间共享项目源代码时,需要剔除node_modules目录
        • 注意:
          • 在项目开发中,一定要把node_modules文件夹,添加到.gitignore忽略文件中
      • 快速创建package.json
        • 在项目根目录下,执行下述命令
          npm init -y

          建议在新建项目以后,不要急于写代码,而是首先执行上述命令创建包管理配置文件

        • 注意:
          • 上述命令只能在英文目录下成功运行,项目文件夹名不要使用中文,不能出现空格
          • 运行npm install命令安装包的时候,npm包管理工具会自动把包的名称和版本号记录到package.json中
      • dependencies节点
        • package.json文件中,有一个dependencies节点,专门用来记录使用npm install命令安装了哪些包
      • 一次性安装所有包
        • 可以运行npm install命令(或npm i)一次性安装所有依赖包
          // 执行npm install命令时,npm包管理工具会先读取package.json中的dependencies节点,依次将相应版本号的包下载到项目中
          npm install
      • 卸载包
        • 可以运行npm uninstall命令来卸载指定包
          npm uninstall moment

          执行命令后,自动把卸载的包从package.json中的dependencies节点中移除

      • devDependencies节点
        • 只在项目开发阶段会用到,而项目上线后不会用到的包,建议安装到devDependencies节点中
        • 使用如下命令,会将包记录到devDependencies节点
          npm i 包名 -D
          // 上述命令是简写形式,等价于:npm i 包名 --save-dev
    • 查看包
      • 查看全局包
        • 显示依赖
          npm ls -g
        • 不显示依赖
          npm ls -g --depth 0
      • 查看当前项目包
        • 显示依赖
          npm ls
        • 不显示依赖
          npm ls --depth 0
      • 查看包的所有版本号
        npm view 包名 versions --json
    • 解决包下载速度慢的问题
      • 使用淘宝NPM镜像服务器
        // 查看当前的下包镜像源
        npm config get registry
        
        // 将下包镜像源切换为淘宝镜像源
        npm config set registry=https://registry.npm.taobao.org/
        
        // 检查下包镜像源是否切换成功
        npm config get registry
      • nrm
        • 为了更方便的切换下包镜像源,可以安装nrm这个小工具,利用nrm提供的终端命令来查看和切换下包镜像源
          // 全局安装nrm
          npm install nrm -g
          
          //查看所有可用的镜像源
          nrm ls
          
          // 将镜像源切换为taobao
          nrm use taobao

          注意:安装nrm需要以管理员身份运行终端

    • 包的分类
      • 项目包
        • 那些被安装到项目的node_modules目录中的包,都是项目包
        • 项目包又分为两大类:
          • 开发依赖包(被记录到devDependencies节点中的包,只在开发期间会用到)
          • 核心依赖包(被记录到Dependencies节点中的包,在开发和项目上线之后都会用到)
            npm i 包名 -D // 开发依赖包
            npm i 包名 // 核心依赖包
      • 全局包
        • 在执行npm install命令时,如果提供了 -g 参数,则会把包安装为全局包
        • 查看全局包安装目录:
          npm root -g

          默认:会被安装到C:\Users\用户目录\AppData\Roaming\npm\node_modules目录下

        • 修改默认安装目录
          • 以存储目录(D:\Softwares\nodejs\node_modules)为例
            • 在目录(D:\Softwares\nodejs)下新建文件夹node_cache
            • 添加系统环境变量
              • 变量名:NODE_PATH
              • 变量值:D:\Softwares\nodejs\node_modules
            • 命令行输入:
              npm config set prefix 'D:\Softwares\nodejs'
              npm config set cache 'D:\Softwares\nodejs\node_cache' 

              注意prefix路径不需要指定node_modules,默认会下载到该目录

    • 规范的包结构
      • 一个规范的包,它的组成解构,必须符合以下3点要求:
        • 包必须以单独的目录而存在
        • 包的顶级目录下必须包含package.json这个包管理配置文件
        • package.json中必须包含name, version, main这三个属性,分别代表:包的名字、版本号、包的入口

七、Express

Express是基于Node.js平台,快速、开放、极简的Web开发框架

  • 安装

    npm install express

    在项目所处的目录中,运行终端命令,即可将express安装到项目中使用

  • nodemon

    • nodemon这个工具,能够监听项目文件的变动,当代码被修改后,nodemon会自动帮我们重启项目,极大方便了开发和调试
    • 安装
      • 终端中执行如下命令,进行全局安装
        npm install nodemon -g
    • 使用
      • 将传统的node命令替换为nodemon命令即可,例如启动test.js
        nodemon test.js

        注意:安装nodemon后需要以管理员身份运行终端

  • 创建基本的Web服务器

    // 1、导入express
    const express = require('express')
    
    // 2、创建Web服务器
    const app = express()
    
    // 3、调用app.listen(端口号,启动成功后的回调函数)启动服务器
    app.listen(8080, () => {
        console.log('Express server running at http://127.0.0.1:8080')
    })
  • 监听GET和POST请求

    • 语法
      // 监听GET请求
      app.get('请求url', function(req, res){/*处理函数*/})
      
      //监听POST请求
      app.post('请求url', function(req, res){/*处理函数*/})
    • 参数
      • 参数1:客户端请求的url地址
      • 参数2:请求对应的处理函数
        • req:请求对象(包含了请求相关的属性和方法)
          • req.query:获取客户端发送过来的查询参数,默认是空对象{}
          • req.params:获取动态匹配到的url参数,默认是空对象{}
          • req.body:接收客户端发送过来的请求体数据,如果不配置解析表单数据的中间件,默认等于undefined
        • res:响应对象(包含了与响应相关的属性与方法)
          • res.send()方法:响应内容给客户端
            • 可以响应JSON对象
            • 也可以响应字符串
    • 示例
      // 导入express
      const express = require('express')
      
      // 创建Web服务器
      const app = express()
      
      app.get('/user',(req, res) => {
          // 调用res.send()方法,向客户端响应一个JSON对象
          res.send({name: '张三', age: 20, gender: '男'})
      })
      
      app.post('/user', (req, res) => {
          // 调用res.send()方法,向客户端响应一个文本字符串
          res.send('请求成功')
      })
      
      app.get('/',(req, res) => {
          // 通过 req.query 可以获取到客户端发送过来的查询参数,默认是一个空对象{}
          console.log(req.query)
          res.send(req.query)
      })
      
      // 注意:这里的id和username是动态参数,格式':参数名'
      app.get('/user/:id/:username',(req, res) => {
          // 通过 req.params 动态匹配到的url参数,默认情况下是一个空对象{}
          console.log(req.params)
          res.send(req.params)
      })
      
      // 调用app.listen(端口号,启动成功后的回调函数)启动服务器
      app.listen(8080, () => {
          console.log('Express server running at http://127.0.0.1:8080')
      })
  • 托管静态资源

    • 通过express.static()函数可以非常方便地创建一个静态资源服务器,在指定的静态目录中查找文件,并对外提供资源的访问路径
    • 托管多个静态资源目录,需要多次调用express.static()函数,会根据目录添加的顺序查找所需文件
    • 在托管的静态资源访问路径之前,可以挂载路径前缀
      // 导入express
      const express = require('express')
      
      // 创建Web服务器
      const app = express()
      
      // 调用express.static()方法,快速对外提供静态资源
      // 优先查找当前目录、其次public目录,再其次查找files目录
      app.use(express.static(__dirname))
      app.use(express.static('./public'))
      app.use(express.static('./files'))
      
      // 挂载路径前缀
      // 通过带有/public前缀来访问public目录中的文件
      app.use('/public',express.static('./public'))
      
      app.listen(8080, () => {
          console.log('express server running at http://127.0.0.1:8080')
      })
  • 路由

    • 为了方便对路由进行模块化管理,不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块
    • 将路由抽离为单独模块的步骤:
      • 创建路由模块对应的js文件
      • 调用express.Router()函数创建路由对象
      • 向路由对象上挂载具体的路由
      • 使用module.exports向外共享路由对象
      • 使用app.use()函数注册路由模块
    • 创建路由模块
      // 路由模块 router.js
      
      // 1、导入express
      const express = require('express')
      
      // 2、创建路由对象
      const router = express.Router()
      
      // 3、挂载具体的路由
      router.get('/user/list', (req, res) => {
          res.send('Get user list.')
      })
      router.post('/user/add', (req, res) => {
          res.send('Add new user.')
      })
      
      // 4、向外暴露路由对象
      module.exports = router
    • 注册路由模块
      const express = require('express')
      const app = express()
      
      // 1、导入路由模块
      const router = require('./router.js')
      
      // 2、注册路由模块,并添加统一的访问前缀 /api
      app.use('/api',router)
      
      // 注意: app.use()函数的作用,就是注册全局中间件
      
      app.listen(8080, () => {
          console.log('express server running at http://127.0.0.1:8080')
      })
  • 中间件

    • 概念
      • 中间件(Middleware),特指业务流程的中间处理环节
      • 当请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理
      • Express的中间件,本质上就是一个function处理函数,形参包含req、res和next
        • next()函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由
      • 多个中间件之间共享同一份 req 和 res。基于这个特性,可以在上游的中间件中,统一为 req 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用
      • 可以使用app.use()
    • 全局生效的中间件
      • 客户端发起的任何请求到达服务器之后,都会触发的中间件,叫做全局生效的中间件
      • 通过调用app.use(中间件函数),即可定义一个全局生效的中间件
      • 可以使用app.use()连续定义多个全局中间件,当客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用
        const express = require('express')
        const app = express()
        
        // 定义第一个全局中间件
        app.use((req, res, next) => {
            console.log('调用了第一个全局中间件')
            next()
        })
        
        // 定义第二个全局中间件
        app.use((req, res, next) => {
            console.log('调用了第二个全局中间件')
            next()
        })
        
        // 定义路由
        app.get('/user', (req, res) => {
            console.log('调用了 /user 这个路由')
            res.send('User Page.')
        })
        
        app.listen(8080, () => {
            console.log('express server running at http://127.0.0.1:8080')
        })
    • 局部生效的中间件
      • 不用app.use()定义的中间件,叫做局部生效的中间件
        const express = require('express')
        const app = express()
        
        // 1、定义中间件函数
        const mw1 = function(req, res, next){
            console.log('调用了局部生效的中间件')
            next()
        }
        
        // 2、定义路由
        // mw1 这个中间件,只在'当前路由中生效',这种用法属于'局部生效的中间件'
        app.get('/', mw1, (req, res) => {
            res.send('Home Page.')
        })
        
        app.get('/user', (req, res) => {
            res.send('User Page.')
        })
        
        app.listen(8080, () => {
            console.log('express server running at http://127.0.0.1:8080')
        })
      • 可以在路由中,通过如下两种等价的方式,使用多个局部中间件:
        // 以下两种方法完全等价,根据喜好选择任意一种
        // 第一个参数是路径url
        // 最后一个参数是处理函数
        // 中间可以是任意多个中间件
        app.use('/', mw1, mw2, (req, res) => {req.send('Home Page.')})
        app.use('/', [mw1, mw2], (req, res) => {req.send('Home Page.')})
    • 中间件使用注意事项
      • 一定要在路由之前注册中间件
      • 客户端发送过来的请求,可以连续调用多个中间件进行处理
      • 执行完中间件的业务代码之后,不要忘记调用next()函数
        • 为了防止代码逻辑混乱,调用next()函数后不要再写额外代码
      • 连续调用多个中间件时,多个中间件之间共享 req 和 res 对象
    • 中间件分类
      • 应用级别的中间件
        • 通过app.use()或app.get()或app.post()绑定到app实例上的中间件,叫做应用级别的中间件
      • 路由级别的中间件
        • 绑定到express.Router()实例上的中间件,叫做路由级别的中间件,它的用法和应用级别的中间件没有任何区别,只不过一个绑定到app实例上,一个绑定到router实例上
      • 错误级别的中间件
        • 专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题
        • 错误级别中间件的 function 处理函数中,必须有4个形参,先后顺序分别是(err, req, res, next)
        • 错误级别的中间件,必须注册在所有路由之后
          const express = require('express')
          const app = express()
          
          // 1、定义路由
          app.get('/', (req, res) => {
              // 人为抛出异常
              throw new Error('服务器的内部发生了错误!')
              res.send('Home Page.')
          })
          
          // 2、定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
          app.use((err, req, res, next) => {
              console.log('捕获了异常:'+err.message)
              res.send('Error!'+ err.message)
          })
          
          app.listen(8080, () => {
              console.log('express server running at http://127.0.0.1:8080')
          })
      • Express内置的中间件
        • 自Express 4.16.0版本开始,Express内置了3个常用的中间件,极大提高了Express项目开发的效率和体验:
          • express.static 快速托管静态资源的内置中间件,例如HTML文件、图片、CSS样式等(无兼容性问题)
          • express.json 解析JSON格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
          • express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,仅在4.16.0+版本中可用)
            const express = require('express')
            const app = express()
            
            // 除了错误级别的中间件,其他的中间件必须在路由之前进行配置
            // 通过express.json()这个中间件,解析表单中的JSON格式数据
            app.use(express.json())
            // 通过express.urlencoded()这个中间件,解析表单中的url-encoded格式的数据
            app.use(express.urlencoded({extended: false}))
            
            // 创建路由
            app.post('/user', (req, res) => {
                // req.body可以获取JSON格式的表单数据和url-encoded格式的数据
                // 不配置任何解析表单的中间件,req.body默认等于 undefined
                console.log(req.body)
                res.send(req.body)
            })
            
            // 指定端口号,并启动服务器
            app.listen(8080, () => {
                console.log('express server running at http://127.0.0.1:8080')
            })
      • 第三方的中间件
        • 由第三方开发出来的中间件,叫做第三方中间件
        • 在项目中,可以按需下载并配置第三方中间件,从而提高项目的开发效率
        • 在express@4.16.0之前的版本中,经常使用 body-parser 这个第三方中间件来解析请求体数据,步骤:
          • 运行 npm install body-parser 安装中间件
          • 使用require导入中间件
          • 调用app.use()注册并使用中间件
            const express = require('express')
            const app = express()
            
            // 导入表单解析中间件 body-parser
            const parser = require('body-parser')
            
            // 使用app.use()注册中间件
            app.use(parser.urlencoded({extended: false}))
            
            // 内置的express.urlencoded中间件,就是基于body-parser这个第三方中间件进一步封装出来的
            // app.use(express.urlencoded({extended: false}))
            
            // 创建路由
            app.post('/user', (req, res) => {
                // req.body可以获取JSON格式的表单数据和url-encoded格式的数据
                // 不配置解析表单的中间件,req.body默认等于 undefined
                console.log(req.body)
                res.send(req.body)
            })
            
            // 指定端口号,并启动服务器
            app.listen(8080, () => {
                console.log('express server running at http://127.0.0.1:8080')
            })
posted @ 2022-10-29 03:56  eliwang  阅读(96)  评论(0编辑  收藏  举报