EggJS系列 | 只会JS也能写后端API
前端也能编写Api
作为一名前端开发人员,我们开发的项目往往离不开后端的Api支持,我们需要与后端配合完成数据联调,数据存放等交互操作,这是单纯前端完成不了的事情,但是有没有什么方法可以让前端人员快速掌握写出Api和服务器打交道呢?
答案就是Node.js
Node.js
相信前端同学不少接触Node.js
,允许在服务器端运行JavaScript
代码,可以打破了前端和后端技术的界限,前端开发者也能够使用熟悉的JavaScript
代码来编写后端服务,从而实现了从前端到后端的全栈开发能力
大家也多多少少会听到expressjs
,koa2
等快速编写Api的框架,但这两个框架因为灵活,门槛低被受开发者喜爱,但是缺点是当您的项目越大,文件数量偏多的情况下,可能不太好管理,因为自由度很高,所以我不太考虑使用他们,更多的是在写Demo
时,去使用它们
// 就像这样子,一个用koa2编写的简单Api就诞生了
// 导入Koa模块
const Koa = require('koa');
// 创建一个新的Koa应用实例
const app = new Koa();
// 定义一个路由处理器,返回"Hello, World!"
app.use(async ctx => {
ctx.body = 'Hello, World!';
});
// 启动服务器,监听3000端口
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
更多的选择
除了express
,koa
框架,我们还能选择什么nodejs
框架,答案有很多,比如比较火的nest.js
,midway.js
,fastify.js
,egg.js
等框架
我们应该怎么选择一个适合我们的框架呢,这里就得先说一下我们的需求
- 前端开发者能够更快上手编写Api
- 框架学习成本较低
最后我们选择的egg.js
这个框架,为什么选择它
- 相比
koa
框架会有多一点的约束和结构,减低的学习成本 eggjs
同样拥有高度的扩展性,它也可以直接使用koa
的中间件- 面向复杂项目,也提供了性能优化,安全控制,分布式部署,日志管理等方案
- 如果遇到问题在网上可查到的资料不少
快速入门Egg.js
打断一下,本文章主要讲重要的部分,一些小细节可能会被遗漏,如果您先完整学习Egg.js框架请移步(Egg.js官网)[www.eggjs.org/zh-CN/intro]
该文章不会讲得很详细,主要还是快速起步Api为主
快速搭建一个eggjs
项目
npm init egg --type=simple
在创建项目的时候,这里有多个选择方向,我们这里选择simple
,因为我们只要一个简单的模板
接下来,根据提示,将项目作者,描述信息填写下即可
打开项目目录,执行npm i
命令进行依赖安装(可能有点小久~)
推荐使用pnpm管理器,性能更好更加快的node包管理工具
npm run dev
当项目跑起来之后,您会看到控制台上有这么几行提示,告诉我们服务启动在http://127.0.0.1:7001
> egg@1.0.0 dev
> egg-bin dev
[egg-ts-helper] create typings\app\controller\index.d.ts (2ms)
[egg-ts-helper] create typings\config\index.d.ts (16ms)
[egg-ts-helper] create typings\config\plugin.d.ts (1ms)
[egg-ts-helper] create typings\app\index.d.ts (1ms)
2024-07-06 15:18:12,442 INFO 45472 [master] node version v20.15.0
2024-07-06 15:18:12,443 INFO 45472 [master] egg version 3.26.1
2024-07-06 15:18:14,985 INFO 45472 [master] agent_worker#1:44516 started (2540ms)
2024-07-06 15:18:18,280 INFO 45472 [master] egg started on http://127.0.0.1:7001 (5837ms)
我们直接用浏览器访问它即可
会在浏览器页面中看到hi,egg
的字样,这是因为我们访问这个链接时,路由指向到了controller/home.js
中的index
这里的home.index
其实也是一个Api
,一个Get
请求的Api
快速crud
Egg.js
路由提供了一个便捷的方式来创建RESTful
风格的路由,我们只需要在路由上编写一个路由地址即可
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
// Restful Api
router.resources('/books', controller.books.index);
};
这一行代码相当于创建了7
个路由地址,请求方法分别是Get
,POST
,PUT
,DELETE
,同样我们也要在controller
里添加对应的处理方法
HTTP方法 | 路由路径 | 路由名称 | 控制器方法 |
---|---|---|---|
GET | /books | books | app.controllers.books.index |
GET | /books/new | new_book | app.controllers.books.new |
GET | /books/:id | book | app.controllers.books.show |
GET | /books/:id/edit | edit_book | app.controllers.books.edit |
POST | /books | books | app.controllers.books.create |
PUT | /books/:id | book | app.controllers.books.update |
DELETE | /books/:id | book | app.controllers.books.destroy |
我们在controller
文件夹中新建books.js
,并编写路由对应的方法
const { Controller } = require('egg');
class BooksController extends Controller {
// 获取所有书籍列表
async index() {
const { ctx } = this;
try {
const books = await ctx.service.books.list();
ctx.body = books;
} catch (error) {
ctx.status = 500;
ctx.body = { error: '获取书籍列表失败' };
}
}
// 新建书籍页面的渲染或数据准备
async new() {
const { ctx } = this;
ctx.body = '显示新建书籍表单或数据准备';
}
// 获取单个书籍详情
async show() {
const { ctx } = this;
const { id } = ctx.params;
try {
const book = await ctx.service.books.find(id);
if (!book) {
ctx.status = 404;
ctx.body = { error: '未找到该书籍' };
} else {
ctx.body = book;
}
} catch (error) {
ctx.status = 500;
ctx.body = { error: '获取书籍详情失败' };
}
}
// 编辑书籍页面的渲染或数据准备
async edit() {
const { ctx } = this;
const { id } = ctx.params;
try {
const book = await ctx.service.books.find(id);
if (!book) {
ctx.status = 404;
ctx.body = { error: '未找到要编辑的书籍' };
} else {
ctx.body = `编辑ID为${id}的书籍表单`;
}
} catch (error) {
ctx.status = 500;
ctx.body = { error: '获取编辑书籍信息失败' };
}
}
// 创建新书籍
async create() {
const { ctx } = this;
try {
const createdBook = await ctx.service.books.create(ctx.request.body);
ctx.status = 201;
ctx.body = createdBook;
} catch (error) {
ctx.status = 400;
ctx.body = { error: '创建书籍失败' };
}
}
// 更新书籍信息
async update() {
const { ctx } = this;
const { id } = ctx.params;
try {
const updatedBook = await ctx.service.books.update(id, ctx.request.body);
if (!updatedBook) {
ctx.status = 404;
ctx.body = { error: '未找到要更新的书籍' };
} else {
ctx.body = updatedBook;
}
} catch (error) {
ctx.status = 500;
ctx.body = { error: '更新书籍信息失败' };
}
}
// 删除书籍
async destroy() {
const { ctx } = this;
const { id } = ctx.params;
try {
const result = await ctx.service.books.delete(id);
if (!result) {
ctx.status = 404;
ctx.body = { error: '未找到要删除的书籍' };
} else {
ctx.status = 204;
}
} catch (error) {
ctx.status = 500;
ctx.body = { error: '删除书籍失败' };
}
}
}
module.exports = BooksController;
上面代码中包含了service
部分的引用,这里需要提一下,service
是一个逻辑封装的抽象层,也是为了保持Controller
的逻辑更简洁,提高代码复用率
我们也需要把service
代码也写一下,在app文件夹中创建service
文件夹,接着在该文件夹下面创建books.js
,并写入以下代码
// app/service/books.js
module.exports = class BooksService {
constructor(ctx) {
this.ctx = ctx;
// 假数据存储
this.books = [
{ id: 1, title: 'Node.js入门', author: '张三', year: 2026 },
{ id: 2, title: 'JavaScript高级程序设计', author: '李四', year: 2027 },
];
}
// 获取所有书籍
async list() {
return this.books;
}
// 根据ID查找书籍
async find(id) {
return this.books.find(book => book.id === parseInt(id));
}
// 创建新书籍
async create(data) {
// 模拟ID自增
const newBook = { id: this.books.length + 1, ...data };
this.books.push(newBook);
return newBook;
}
// 更新书籍信息
async update(id, updates) {
const index = this.books.findIndex(book => book.id === parseInt(id));
if (index !== -1) {
this.books[index] = { ...this.books[index], ...updates };
return this.books[index];
}
return null;
}
// 删除书籍
async delete(id) {
const index = this.books.findIndex(book => book.id === parseInt(id));
if (index !== -1) {
this.books.splice(index, 1);
return true;
}
return false;
}
};
到这里,一个简单的crud
代码就写好了,是不是很简单
当我们发送一个请求时,egg.js
先是走了router.js
,判断请求路由找到对应的控制器(controller
)中的函数去执行,最后通过赋值数据到ctx.body
属性上进行返回数据
当然,这只是一个简单的例子,当我们实际开发的时候,需要考虑的东西就会变得比较多了,例如传参的校验,从数据库中调取数据等...
接下来还会涉及到ORM
框架,Egg.js
插件,路由中间件管理等更深的学习
我并不打算将这些部分通过理论或者案例的方式讲出来,而是想要通过简单理论+实践的方式搭建一个通用Api
的模板,来向大家展示和学习
接下来我会通过多篇文章的方式,一步一步教大家如何快速构建一个后端Api
应用
点个关注,追更不迷路👻
转载自:https://juejin.cn/post/7398045554922684428