Node.js 核心知识点 - Koa 框架

一、Koa 基本概念

官网:Koa - next generation web framework for node.js

1、Koa 是什么?

Koa 是一个基于 Node.js 的轻量级 web 框架,由Express团队创造。Koa 的设计理念是使用现代的 JavaScript 特性(如 async/await)来增强开发体验,并提供更优雅、灵活的方式来构建 Web 应用。

2、Koa 核心概念

中间件机制

1、中间件的核心概念

Koa 使用中间件来处理 HTTP 请求。每个中间件是一个异步函数,可以执行一些操作 ,然后将控制权传递给下一个中间件。这种机制使得开发者可以很方便地编写和组合功能。

2、中间件的类型
(1) 应用级中间件

这些中间件绑定到 Koa 应用程序对象上 ,并在每个请求处理周期中执行。应用级中间件通常用于执行跨路由的共享任务,比如日志记录、错误处理、身份验证等。

javascript 复制代码
// 应用级中间件
app.use(async (ctx, next) => {
    console.log('应用级中间件 - 这里可以处理每个请求前的共享任务');
    await next();
});
(2) 路由级中间件

这些中间件与特定路由相关联,只在特定路由匹配时执行 。路由级中间件用于在特定路由上执行特定任务,比如请求验证、权限控制等。

javascript 复制代码
// 路由级中间件
router.get('/', async (ctx, next) => {
    console.log('路由级中间件 - 只在根路由匹配时执行');
    await next();
    ctx.body = 'Hello, World!';
});
(3) 错误处理中间件

错误处理中间件用于捕获应用程序中发生的错误,并作出相应的处理。在 Koa 中,错误处理中间件通常是最后一个中间件,用来处理未捕获的错误并发送适当的响应给客户端。

javascript 复制代码
// 错误处理中间件
app.use(async (ctx, next) => {
    try {
        await next();
    } catch (err) {
        console.error('发生错误:', err.message);
        ctx.status = err.status || 500;
        ctx.body = {
            error: err.message
        };
    }
});
(4) 内置中间件

Koa 提供了一些内置中间件,比如 koa-bodyparser 用于解析请求体,**koa-static**用于提供静态文件服务等。这些内置中间件提供了常用功能的便捷实现。

javascript 复制代码
// 错误处理中间件
app.use(async (ctx, next) => {
    try {
        await next();
    } catch (err) {
        console.error('发生错误:', err.message);
        ctx.status = err.status || 500;
        ctx.body = {
            error: err.message
        };
    }
});
3、中间件的 ctx、next
ctx - 核心功能: 获取请求信息、发送响应内容
next - 核心功能: 将控制权传递给下一个中间件函数。
javascript 复制代码
app.use(async (ctx, next) => {
    // 这是一个中间件函数
    console.log('这是第一个中间件');

    // 调用下一个中间件
    await next();

    console.log('第一个中间件执行完成');
});

app.use(async (ctx, next) => {
    // 这是第二个中间件
    console.log('这是第二个中间件');

    // 结束当前中间件,不调用 next(),则后续中间件将不会执行
});

app.use(async (ctx, next) => {
    // 这是第三个中间件
    console.log('这是第三个中间件');

    // 调用下一个中间件
    await next();
});

/**
 * 打印内容为:
 *  这是第一个中间件
 *  这是第二个中间件
 *  第一个中间件执行完成
 *  
 */

注意有些中间件在其内部会默认调用 next() ,这样可以确保中间件链中的下一个中间件会被执行。例如 koa-router 中间件、koa-bodyparser 中间件、koa-static 中间件等等

javascript 复制代码
const Router = require('koa-router');
const router = new Router();

router.get('/route', async (ctx, next) => {
    // 处理路由逻辑
});

app.use(router.routes());

二、Koa 怎么用

1、基本使用

(1)下载必要中间件 koa(框架)、koa-bodyparser(路由)

javascript 复制代码
npm install koa koa-router koa-bodyparser

(2)创建一个 Koa 应用

javascript 复制代码
// 导入中间件
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');

const app = new Koa();
const router = new Router();

// 使用 bodyparser 中间件(内部中间件、解析请求体)
app.use(bodyParser());

// 定义路由
router.get('/', async (ctx) => {
    ctx.body = '欢迎访问后台接口';
});

// 定义其他接口
router.get('/api/data', async (ctx) => {
    // 返回示例数据
    ctx.body = { message: '这是一个示例接口' };
});

// 注册路由
app.use(router.routes());

// 启动服务器
app.listen(3000, () => {
    console.log('服务器运行在 http://localhost:3000');
});

(3)启动 Koa 应用、并测试

2、项目中实际使用

(1)搭建基本目录结构

(2)搭建基本服务器

app.js - 入口文件 不是内部中间件都需要安装

javascript 复制代码
// 导入中间件
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser'); // 内部中间件
const cors = require('@koa/cors')
const static = require('koa-static');

const app = new Koa();
const router = new Router();

// 使用 bodyparser 中间件(解析请求体)
app.use(bodyParser());
// // 使用 cors (处理跨域)
app.use(cors());

// 定义路由
router.get('/', async (ctx) => {
    ctx.body = '欢迎访问后台接口';
});
// 访问静态资源路由
app.use(static('public'));

// 注册路由
app.use(router.routes());

// 错误处理中间件
app.use(async (ctx, next) => {
  try {
      await next();
  } catch (err) {
      console.error('发生错误:', err.message);
      ctx.status = err.status || 500;
      ctx.body = {
          error: err.message
      };
  }
});

// 启动服务器
app.listen(3000, () => {
    console.log('服务器运行在 http://localhost:3000');
});

(3)创建数据库连接对象并导出

下载 mysql
javascript 复制代码
npm i mysql
db文件夹下创建 db.js 文件、内容如下
javascript 复制代码
//导入 mysql 模块
const mysql = require('mysql')

// 创建数据库连接对象
const db = mysql.createPool({
  host: '127.0.0.1',
  user: 'root',
  password: '123456',
  database: 'wallpaper'
})

// 向外共享数据库连接对象
module.exports = db

(4)操作数据库、并优化项目结构。

1、定义路由处理函数并导出
javascript 复制代码
// 导入数据库连接对象
const db = require('../db/db.js')

// 路由处理函数
exports.apiTest = async (ctx) => {
  // 查询的 sql 语句
  const sql = `SELECT * FROM classify`
  const result = await new Promise((resolve, reject) => {
    // 执行查询的 sql 语句
    db.query(sql, (err, result) => {
      // 执行错误
      if(err) {
        resolve(err)
      }
      resolve(result)
    })
  })
  // 返回响应信息
  ctx.body = result;
}
2、定义路由对象挂载路由,并导出路由对象
javascript 复制代码
// 导入路由
const Router = require('koa-router');
// 导入路由处理函数
const { apiTest } = require('../router_handle/router_hander.js')

// 创建路由对象
const router = new Router();


router.get('/apiTest', apiTest);

module.exports = router
3、修改入口文件 app.js
javascript 复制代码
// 导入中间件
const Koa = require('koa');
const bodyParser = require('koa-bodyparser'); // 内部中间件
const cors = require('@koa/cors')
const static = require('koa-static');

const app = new Koa();

// 导入路由对象
const router = require('./router/router.js')

// 使用 bodyparser 中间件(解析请求体)
app.use(bodyParser());
// // 使用 cors (处理跨域)
app.use(cors());

// 访问静态资源路由
app.use(static('public'));

// 注册路由
app.use(router.routes());

// 错误处理中间件
app.use(async (ctx, next) => {
  try {
      await next();
  } catch (err) {
      console.error('发生错误:', err.message);
      ctx.status = err.status || 500;
      ctx.body = {
          error: err.message
      };
  }
});

// 启动服务器
app.listen(3000, () => {
    console.log('服务器运行在 http://localhost:3000');
});
4、测试 apiTest 接口

这里用的 Apifox:Apifox

(5)文件处理接口的构建

1> 安装 @koa/multer - 处理 multipart/form-data 类型的表单数据,特别是文件上传。

npm install @koa/multer

2> 设置文件存储选项和存储方式、并挂载上传接口路由上
javascript 复制代码
// 导入 @koa/multer
const multer = require('@koa/multer')

// 设置存储选项
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
      cb(null, 'public/file/'); // 文件存储路径
  },
  filename: function (req, file, cb) {
      const fileExtension = file.originalname.split('.').pop(); // 获取文件扩展名
      cb(null, file.originalname.split('.')[0] + '-' + Date.now() + '.' + fileExtension); // 文件名设置为原文件名+时间戳
  }
});

// 设置存储方式为内存存储
const upload = multer({ storage: storage });

router.post('/upload', upload.single('file'), async (ctx) => {
  ctx.body = {
      status: 200,
      message: '文件上传成功',
      data: {
        fileUrl: `${url}:${port}` + '/public/file' + ctx.file.filename, // 返回存储的文件路径(${url}:${port}替换成你启动的服务器地址)
        fileName: ctx.file.originalname, // 原始文件名称
        saveFileName: ctx.file.filename // 存储的文件名称

      }
  };
});

更多接口持续更新中...

相关推荐
f8979070701 小时前
layui动态表格出现 横竖间隔线
前端·javascript·layui
鱼跃鹰飞1 小时前
Leecode热题100-295.数据流中的中位数
java·服务器·开发语言·前端·算法·leetcode·面试
二十雨辰2 小时前
[uni-app]小兔鲜-04推荐+分类+详情
前端·javascript·uni-app
霸王蟹2 小时前
Vue3 项目中为啥不需要根标签了?
前端·javascript·vue.js·笔记·学习
小白求学12 小时前
CSS计数器
前端·css
Anita_Sun2 小时前
🌈 Git 全攻略 - Git 的初始设置 ✨
前端
lucifer3113 小时前
深入解析 React 组件封装 —— 从业务需求到性能优化
前端·react.js
谢尔登3 小时前
【Node.js】worker_threads 多线程
node.js
等什么君!3 小时前
复习HTML(进阶)
前端·html
儒雅的烤地瓜3 小时前
JS | 如何解决ajax无法后退的问题?
前端·javascript·ajax·pushstate·popstate事件·replacestate