Skip to content
目录

express 快速入门

简介

作为前端开发,Nodejs 已经成了很多公司对我们这一岗位的要求。

而 express 是非常受欢迎的 Nodejs Web 框架,常用于构建 Web 应用和 API。它帮助我们封装了 Nodejs 底层的 API,屏蔽了大量的繁琐的细节,让我们只需要关注业务开发就行了,极大的降低了学习的成本。

如何使用 express 快速搭建一个的后端服务,我们主要围绕以下几个部分:

  • 路由
  • 中间件
  • 静态文件服务
  • 错误处理

演示环境

  • 电脑 - Windows 10
  • Node - v16.15.0
  • Npm - 9.4.0
  • Express - 4.18.2

快速搭建后端服务

为了便于大家去理解 express 对 nodejs 做了哪些封装,在使用 express 之前,我们先来看下使用 nodejs 内置的 http 模块是怎么搭建 node 服务的。

原生 http 模块

  1. 创建 http-server 文件夹并进入
  2. 执行 npm init 命令,然后一路回车,生成 package.json 文件。
  3. 创建 server.js,并添加如下代码:
js
const http = require('http')

const server = http.createServer((req, res) => {
  res.statusCode = 200
  res.setHeader('Content-Type', 'text/html')
  res.end('hello world')
})

server.listen(3000, () => {
  console.log('服务已启动...')
})
  1. 在控制台中运行:
sh
node server.js
  1. 用客户端/浏览器访问服务器 http://127.0.0.1:3000

使用 express 搭建服务

  1. 创建 express-server 文件夹并进入。
  2. 执行 npm init 命令,然后一路回车,生成 package.json 文件。
  3. 执行 npm install express 来安装 express 模块。然后改写 server.js。
  4. 创建 server.js,并添加如下代码:
js
const express = require('express')

const app = express()

app.get('/', (req, res) => {
  res.send('hello world')
})

app.listen(3000, () => {
  console.log('服务已启动...')
})
  1. 在控制台中运行:
sh
node server.js
  1. 用客户端/浏览器访问服务器 http://127.0.0.1:3000

注意

express 属于第三方模块,需要先安装依赖后才能使用。

Request 和 Response 对象

  • Request 对象是请求对象,就是回调函数中的 req 参数,主要是网络请求中带的一些属性,比如参数, cookie 等等。

  • Response 对象是响应对象,就是回调函数中的 res 参数,可以执行一系列的响应操作,比如给客户端响应内容和状态等等。

查看 Request 和 Response 对象的所有 API

路由机制

思考:我们在向后端发请求时通过什么去区分接口的?

答:请求方式+接口 url

我们在 express 中,定义路由的方式是:

js
app.METHOD(URL, CALLBACK)

这种方式就可以通过请求方式和 URL 来帮我们区分不同的请求,从而去执行不同的响应。

nodemon

nodemon 能够检测工作区代码的变化,并自动重启。

执行 npm install nodemon -D 安装 nodemon,然后修改 package.json 文件中的 start 命令:

json
{
  "name": "express-server",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "start": "nodemon server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^2.0.20"
  }
}

再执行 npm start 启动服务,之后我们再修改代码就不需要手动的重启服务了。

核心概念

路由

在浏览器中我们想要访问百度,只需要知道百度的地址就行了,路由也是类似的概念,我们想要知道客户端调用的是哪个接口,就是通过路由来判断的。

路由方法

Express 支持对应于 HTTP 方法的以下路由方法:get、post、put、delete 等等。

使用方法为:

js
app.METHOD(URL, CALLBACK)

示例:

js
const express = require('express')

const app = express()

// get 请求
app.get('/', (req, res) => {
  res.send('hello world')
})

// post 请求
app.post('/about', (req, res) => {
  res.send({ name: 'itheima', age: 18 })
})

路由路径

路由路径一般是字符串。

匹配根路径:

js
app.get('/', (req, res) => {
  res.send('Hello World!')
})

匹配特定路径:

js
app.get('/user/list', (req, res) => {
  res.send('User List')
})

匹配路径模式:

js
app.get('/user/:userId', (req, res) => {
  res.send(req.params)
})

路由拆分

当我们的路由越来越多,比如有用户相关的路径,有系统相关的路径,如果不加以管理,会导致代码变得难以维护和理解。

为了解决这个问题,可以将路由处理程序拆分成多个文件,每个文件专门处理一组相关的路由,使代码更加模块化,易于维护和扩展。

拆分前

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

app.get('/user/list', (req, res) => {
  res.send('User List')
})

app.get('/user/:userId', (req, res) => {
  res.send(req.params)
})

app.listen(3000)

拆分后

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

const user = express.Router() // 创建子路由

user.get('/list', (req, res) => {
  res.send('User List')
})

user.get('/:userId', (req, res) => {
  res.send(req.params)
})

app.use('/user', user) // 注册子路由

app.listen(3000)

中间件

中间件是一个非常重要的概念,它可以在请求被路由匹配到具体的处理程序时执行一些额外的逻辑,比如处理 CORS 跨域,处理请求错误等。中间件本质上是一个函数,它们可以按照一定的顺序被执行。

在 Express 中,中间件可以通过 app.use() 方法来注册:

js
app.use(someMiddleware)

通过中间件实现 CORS 实现跨域:

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

// 允许跨域
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
  next()
})

// ...省略

注意

如果中间件函数不调用 next() 函数,那么请求将被挂起,不会继续向下传递。

静态文件服务

在 Web 应用程序中,通常需要向客户端提供静态资源,如 HTML、CSS、JavaScript、图像、视频等文件。

为了方便地处理静态资源,Express 提供了一个内置的中间件函数 express.static(),用于向客户端提供静态文件服务。

这个中间件函数可以将目录下的静态文件映射到一个 URL 的路径上,从而可以通过浏览器访问这些静态文件。

静态文件准备

假设我们的静态资源在 public 下面:

sh
public
├── css
   └── style.css
└── img
    └── logo.png

中间件

在使用 express.static() 中间件函数时,需要指定静态文件所在的目录路径和 URL 的路径。

我们只需要在 server.js 中添加一行代码:

js
app.use(express.static('public'))

这意味着当客户端请求静态文件时,Express 将会在 public 目录下查找相应的文件并将其发送给客户端。

然后我们就可以通过下面的路径访问到这些资源了:

注意

express.static() 中间件函数只能处理静态文件,不能处理动态请求。如果需要处理动态请求,需通过路由函数来处理。

处理错误

当应用程序出现错误时,如何正确地处理错误并向用户提供有用的信息,是一个好的应用程序设计的重要方面。

我们在访问一些路由时有可能这个路由没有定义,这个时候就会返回 404 的状态码,或者服务器内部代码出错返回 500 错误码,这些情况是在开发中经常碰到的,那么服务端应该如何处理这些异常的情况呢?

在 Express 中,错误处理可以通过中间件来实现。

注意

错误处理中间件应该放在所有路由的后面。

404 错误

在 server.js 中添加如下代码:

js
// 处理 404 错误
app.use('*', (req, res) => {
  res.status(404).send(`<h1>404 找不到你要的页面~</h1>`)
})

* 表示匹配任何路径,status(404) 表示修改状态码为 404,将此中间件放在所有路由后面,捕获路径匹配失败的请求。

再次提醒:一定是放在所有路由的后面,只有前面的路由都匹配不上才会匹配到 * 的这个路由。

处理内部错误

在 server.js 中添加如下代码:

js
// 处理服务器错误
app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('<h1>服务器好像开小差了~</h1><p>过一会儿再试试看吧!</p>')
  next()
})
//

温馨提示

  • 处理服务器错误,需要四个参数,且参数的顺序固定为 err, req, res, next
  • 处理服务器错误,建议放到 404 后面,为什么?

参考答案:如果将错误处理中间件放在 404 中间件之前,那么发生 404 错误时,错误处理中间件也会被执行,这会导致不必要的错误响应。

拓展阅读

其他 Node.js Web 框架。

如果你只想快速搭建一个模拟的后端 API,方便前端开发和测试,推荐使用 json-server。而 express 则更适合用于构建复杂的 Web 应用程序,提供更多的自定义和扩展能力。

根据 MIT 许可证发布