Node.js Web框架入门:使用Express搭建简单应用并深入了解中间件与错误处理(下)

上节课我们讲到使用express脚手架快速搭建express应用,本次课程我们继续聊聊express。

  1. 开始将app.js中的内容改成ts
  • 改写
    • 先直接将内容复制到app2.ts
    • yarn add @types/node@16.15.0 --dev,这样才能使用require
    • yarn add @types/express@4.16.1 --dev,这样才能使用require
    • 可以用import代替require
    • 可以用const代替var
    • 需RequestHandler和ErrorRequestHandler断言
js 复制代码
import { ErrorRequestHandler, RequestHandler } from 'express-serve-static-core';
...
app.use(function (req, res, next) {
  next(createError(404));
} as RequestHandler);
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  res.status(err.status || 500);
  res.render('error');
  next()
} as ErrorRequestHandler);

module.exports = app;
  • 将bin/www中的入口改为app2.ts
  • 添加yarn start ts脚本,将node改为ts-node
  • 其它地方想要用ts的也需要这样改
  1. 深入了解express编程模型
  • app.use()的作用
  • 创建express-demo2,使用刚才创建的starter
bash 复制代码
clone git@github.com:codingories/express-starter-1.git .
yarn install
  • 删除app.js自己重新写一下,运行node-dev app.js
js 复制代码
const express = require('express')

const app = express()

app.use((request, response, next)=> {
  console.log(request.url)
  response.write('hi')
  next()
})

app.use((request, response, next)=> {
  console.log(2)
  response.write('hi')
  next()
})

app.use((request, response, next)=> {
  response.end()
  next()
})


app.listen(3000, () => {
  console.log('正在 listen 3000')
})
  • 访问localhost:3000,得到hihi,通过这个例子我们可以简单的体会一下app.use使用中间件
  1. 什么是中间件
  • express的编程模型
  • 中间件的概念:通过app.use注册了一系列中间件。允许你在请求到达路由处理之前或之后执行一些操作
  • 例子
js 复制代码
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
  • 中间件的优点
    • 这种模型使得每个功能都能通过一个函数实现
    • 然后通过app.use将这个函数整合起来
    • 如果把函数放到文件或npm里,就实现了模块化
  • 自己写一个中间件,新建logger.js
js 复制代码
const logger = (prefix) => {
  return (request, response, next) => {
    console.log(`${prefix} ${request.url}`)
    next()
  }
}

module.exports = logger
  • 然后在app.js中使用,这样就独立完成了一个logger的中间件
js 复制代码
const fn = logger('dev')

app.use(fn)

app.use((request, response, next)=> {
  response.end()
  next()
})
  • 题外话,我们可以将以下代码设置成live template来快速生成,之后直接输入app.use加tab就可以生成,$end表示停的位置
js 复制代码
app.use((request, response, next)=> {

})
  • app.use如何实现路由
js 复制代码
app.use((request, response, next)=>{
  if(request.path==='/xxx' && request.method === 'get') {
    request.write('home')
  }
  next()
})
  • 路由更简单的实现方式
js 复制代码
const fn = () => {}
app.use('/aaa', fn)
app.get('/yyy', fn)
app.post('/zzz', fn) 
app.route('/xxx').all(f1).get(f2).post(f3)
  • 处理路由我们更推荐用express.Router()
    • 通过express.Router(),可以将每个路由的处理逻辑独立分离,使代码更易于维护。
    • 具体代码
js 复制代码
// 创建一个路由器
const router = express.Router();

// 定义路由处理程序
router.get('/', (req, res) => {
  res.send('首页');
});

router.get('/about', (req, res) => {
  res.send('关于我们');
});

router.get('/contact', (req, res) => {
  res.send('联系我们');
});

// 将路由器挂载到'/app'路径上
app.use('/', router);

app.listen(3000, () => {
  console.log('正在 listen 3000')
})
  1. 错误处理
  • 例子
js 复制代码
// 模拟一个可能出错的路由处理
app.get('/error', (req, res, next) => {
  // 在这个例子中,模拟一个异步操作,比如查询数据库时发生了错误
  setTimeout(() => {
    // 模拟错误
    next(new Error('这是一个模拟的错误'));
  }, 1000);
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);

  // 判断错误类型并发送相应的响应
  if (err instanceof SyntaxError) {
    res.status(400).send('Bad Request');
  } else {
    res.status(500).send('Something went wrong!');
  }
});

// 启动服务器
app.listen(3000, () => {
  console.log('服务器正在监听端口 3000');
});
  • next(error),会直接进入errorHandler,不执行后面的中间件
  • 如何自定义errorHandler
js 复制代码
app.use((err, req, res, next) => {
  ...
});
  1. 总结
  • 本次课程我们深入了解Express的编程模型与中间件。
  • 首先,通过Curl命令、HTTP请求与响应的处理,我们夯实了对Web框架的基础认识。
  • 接着,我们将探讨Express的编程模型,了解中间件的概念与优势,并通过自定义中间件和路由进行实践。
  • 进一步地,我们将学习错误处理的重要性,通过示例了解如何处理可能出错的路由,以及如何自定义错误处理中间件。
    • 通过这些实例,我们将更深入地了解Express的强大功能。
  • 最后,让我们继续深入学习Express,为构建强大的Node.js应用程序打下坚实基础。
相关推荐
鬼手点金41 分钟前
nanoGPT/nanochat 能做出 DeepSeek/Qwen 这样的大模型吗?
服务器·前端·javascript·bug·openclaw
蛋蛋的就会顺顺的1 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
程序员Sunday1 小时前
TypeScript 的 any、unknown、never 有什么区别?
前端·面试·typescript
余槐i1 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
朱涛的自习室1 小时前
70 美金的 Beyond Compare,我让 Gemini 4 和 DeepSeek 造个开源免费版(Day 2)
android·前端·人工智能
需要8262 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
码艺-Alimjan2 小时前
Tauri 源码备份 · 打包 & 解压 总结,源码收集之路
前端·javascript·vue.js
小马不起床2 小时前
零基础玩转 FastAPI_11:前端后台管理页面
前端·状态模式·fastapi
凤山老林3 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
子非鱼a3 小时前
【文件上传】一个普普通通的edu16
前端