跳至主要內容

框架API方法

微信公众号:储凡About 11 min

框架API方法

express模块提供了很多API方法,要了解、使用这些API去解决一些实际问题,首先需要安装:

## 安装express
npm install express --save

Express框架主要提供了express对象application对象request对象response对象router对象的API方法,往往在使用Express框架时, 项目入口文件的第一行就是对框架的引用,例如:

// 引入express模块
const express=require('express')

因为,这些API方法都来源express模块,针对不用的应用场景做的一些封装

express()方法

express模块的入口其实是到处一个函数,通常是像上面引入一样,用变量express来接受,查看源码:

express入口函数
express入口函数

可以看出引入的express模块,实质是导出一个createApplication方法,用来创建express的应用实例,这也说明为什么往往在引入express后, 第二行代码就是创建application对象实例

// 导入模块
const express = require('express')
// 创建express应用对象
const app = express()

设置可以从源码中看到,这个application对象上还绑定了requestresponse两个对象,使用Object.create创建的、分别处理请求和响应。

除了提供创建app实例的方法,在源码导出时,还在express模块上挂载一些中间件,查看源码:

这里也许会有疑惑,导出的一个函数,使用express变量去接收时,创建出app实例对象,为什么在函数上又能去挂载一些中间件呢? 其实在js发展早期,很多概念都是利用函数、对象、原型链去实现的,导出的函数可以理解为构造函数,挂载的中间件实质上也是一些方法、对象, 可以理解为使用static关键字标记的静态方法。

总之,如果将这里导出的express理解为一个,将createApplication方法理解为构造函数,将中间件理解为静态方法,应该就要好理解很多。

js也是到ES6推出后才有了类的概念,并且也是利用函数+对象来实现的。

这里的理解,我在阅读源码的时候发现,结合Java的面向对象思想获取更好理解,接下来就说说express类上面挂载的静态方法、中间件

数据处理

Express框架内置中间件

  • express.json()
  • express.raw()
  • express.text()
  • express.urlencoded()

都是基于body-parser模块,实质上就是利用body-parser中的json()raw()text()urlencoded()方法,查看源码:

具体用法可以参考模块:body-parseropen in new window

可以对客户端请求传递的数据做处理,前置中间件处理好数据,交给下游的中间件、处理函数来实现逻辑

数据处理中间件的一些参数含义:

const express = require('express')
const app = express()

express.raw({
  // 可选参数,布尔类型
  // 是否禁用压缩的请求体数据,默认为true,false时拒绝请求数据
  inflate: undefined,
  // 可选参数,数字或字符
  // 限制请求体的大小,默认100kb
  limit: undefined,
  // 可选参数,字符或字符数组
  // 约定什么类型的数据会被该中间件处理,默认值:"application/octet-stream"
  type: [],
  // 可选参数,函数包含req、res、buffer、encoding四个参数
  // 提供原始的请求正文Buffer数据、编码等信息,可以通过抛错来终止解析
  verify(req, res, buf, encoding) {
  }
})

express.json({
  // ... 除raw函数包含的参数外,还额外包含

  // 可选参数,布尔类型
  // 设置是否使用严格模式,默认为true,只接收对象和数组
  // 设置false时,接收一切可以JSON.parse()处理的数据
  strict: true,
  // 可选参数,函数类型
  // 设置的这个函数,将直接放在JSON.parse()的第二个参数中使用
  // 参考JSON.parse()的API:
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter
  reviver(key, value) {
  }
})

express.text({
  // ... 除raw函数包含的参数外,还额外包含

  // 可选参数,字符串
  // 如果请求的header中没有指定Content-Type类型,指定文本内容的编码类型, 默认utf-8
  defaultCharset: undefined
})

express.urlencoded({
  // ... 除raw函数包含的参数外,还额外包含

  // 可选参数,布尔类型
  // 运行定制模块类解析URL地址中的参数
  // false时,使用querystring模块解析
  // true时,使用qs模块解析
  extended: undefined,
  // 可选参数,数字类型
  // 允许URL地址中传递的参数最大字段个数,默认为1000
  // 当参数个数超出时,返回客户端 413 状态码,表示请求体过大
  parameterLimit: undefined
})


这里要重点提一下JSON.parse()的用法,例如:

JSON.parse("{}"); // {}
JSON.parse("true"); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse("null"); // null

JSON.parse(
  '{"p": 5}',
  (key, value) =>
    typeof value === "number"
      ? value * 2 // return value * 2 for numbers
      : value, // return everything else unchanged
);
// { p: 10 }

参考:JSON.parse() API用法open in new window

静态资源

Express中内置的中间件功能。提供静态文件托管管理,基于serve-static

模块用法参考:serve-staticopen in new window

express.static()的基础用法:

const express = require('express')
const app = express()
const path = require('path')
// 服务启动端口
const port = 3000

// 指定接口的根路径映射到资源的根目录
app.use(express.static('public'))

// 设置不同的路径映射
app.use('/static', express.static('public'))

// 使用绝对路径
app.use('/static-back', express.static(path.join(__dirname, 'public')))


/**
 * 服务启动,监听端口
 */
app.listen(port, () => {
  console.log(`quick-start app listening on port ${port}`)
})

基于Express框架,关于静态文件托管,单独开了一篇做介绍,传送门:静态资源托管

路由

提供express.Router()创建一个新的路由器对象,约定接口的请求路径,例如:

const express = require('express')
const router = express.Router()

// 当前路由配置中间件
router.use(async(req, res, next) => {
  console.log('打印req对象', req)
  console.log('打印res对象', res)
  // 只有执行next()函数,请求才会继续向下走处理逻辑
  await next()
})

// 设置该路由管理的路径
router.get('/get-request', async(req, res, next) => {
  console.log('完成接口的一些业务逻辑')

  res.json({
    code: 200,
    message: '响应成功'
  })
})

express.Router()创建路由器对象时也支持一些额外的参数,查看源码:

其中:

  • caseSensitive:配置是否对路由地址大小写敏感,布尔类型。默认false,即:大小写不敏感,/test/Test效果一样。
  • mergeParams:保留req.params父路由器的值,布尔类型。如果父级和子级的参数名称有冲突,则子级的值优先。默认false
  • strict:是否开始严格模式路由,布尔类型。默认false,即:/test/test/效果一样

路由器的用途还有很多,不仅支持多种请求类型的接口定义,还能分层管理,后面将单独开一篇详细讲讲,传送门:路由的使用

application对象

request对象

response对象

router对象

参考