赞
踩
目录规划
一个好的项目离不开一个好的目录规划,当然你也可以按照自己思路来做
mongodb-serverless-node-rest-api
├── package.json
├── .env
├── serverless.yml
├── app
| ├── handler.js
│ ├── controller
│ | └── books.js
│ └── model
│ | ├── db.js
│ | ├── books.js (可选)
│ └── utils
│ ├── message.js
└── test
└── controller
└── books.test.js
项目创建、插件安装
这一次我没有直接使用 MongoDB 驱动,而用的 mongoose 来代替 MongoDB 操作。
$ serverless create --template hello-world --path mongodb-serverless-node-rest-api
$ npm init
$ npm i dotenv mongoose -S
$ npm i serverless-offline --save-dev
创建 .env 配置文件
将配置独立出来放入 .env 配置文件,统一管理。
DB_URL=mongodb+srv://admin:admin123456@cluster0-on1ek.mongodb.net/test?retryWrites=true&w=majority
DB_NAME=study1
DB_BOOKS_COLLECTION=books
创建 Model
app/model/db.js
const mongoose = require(‘mongoose’);
mongoose.connect(process.env.DB_URL, {
dbName: process.env.DB_NAME,
});
app/model/books.js
Mongoose 的一切始于 Schema。每个 schema 都会映射到一个 MongoDB collection ,定义这个 collection 里的文档构成。
const mongoose = require(‘mongoose’);
const BooksSchema = new mongoose.Schema({
name: String,
id: { type: Number, index: true, unique: true },
createdAt: { type: Date, default: Date.now },
});
module.exports = mongoose.models.Books || mongoose.model(‘Books’, BooksSchema, process.env.DB_BOOKS_COLLECTION);
使用 mongoose 创建 model,serverless-offline 运行之后调用多次,可能会出现以下问题
OverwriteModelError: Cannot overwrite Books
model once compiled.
这个错误是因为你已经定义了一个 Schema,之后又重复定义该 Scheme 导致的,错误代码如下所示:
module.exports = mongoose.model(‘Books’, BooksSchema, process.env.DB_BOOKS_COLLECTION);
解决这个问题,一种方案是要保证仅实例化一次,正确代码如下所示,另一种是在 serverless offline 之后加上 --skipCacheInvalidation 参数跳过 require 缓存无效操作,详情可参见 serverless-offline/issues/258。
module.exports = mongoose.models.Books || mongoose.model(‘Books’, BooksSchema, process.env.DB_BOOKS_COLLECTION);
编写业务逻辑 Books
将业务逻辑处理放在 Books 这个类里面,并且可以不依赖于外部的任何服务,this.BooksModel 这个在测试时可以模拟数据进行传入。做到 业务逻辑与 FaaS、BaaS 的分离。
app/controller/books.js
const message = require(‘…/utils/message’);
class Books {
constructor(BooksModel) {
this.BooksModel = BooksModel;
}
/**
创建 Book 数据
@param {*} event
*/
async create(event) {
const params = JSON.parse(event.body);
try {
const result = await this.BooksModel.create({
name: params.name,
id: params.id,
});
return message.success(result);
} catch (err) {
console.error(err);
return message.error(err.code, err.message);
}
}
/**
更新
@param {*} event
*/
async update(event) {
try {
const result = await this.BooksModel.findOneAndUpdate({ id: event.pathParameters.id }, {
$set: JSON.parse(event.body),
}, {
$upsert: true,
new: true
});
return message.success(result);
} catch (err) {
console.error(err);
return message.error(err.code, err.message);
}
}
/**
查找所有 Books 数据
@param {*} event
*/
async find() {
try {
const result = await this.BooksModel.find();
return message.success(result);
} catch (err) {
console.error(err);
return message.error(err.code, err.message);
}
}
/**
删除一条数据
@param {*} event
*/
async deleteOne(event) {
try {
const result = await this.BooksModel.deleteOne({
id: event.pathParameters.id
});
if (result.deletedCount === 0) {
return message.error(1010, ‘数据未找到!可能已被删除!’);
}
return message.success(result);
} catch (err) {
console.error(err);
return message.error(err.code, err.message);
}
}
}
module.exports = Books;
编写 handler
在 handler 里 event、context 这些参数是由 FaaS 平台提供,上面我们又把业务逻辑单独放置于 Controller 下的 Books.js 里,这样做好处是假如我们要从一个平台迁移到另一个平台,只需要修改 handler.js 里 Books 的调用方式即可,业务逻辑是不受影响的。
对于这种初始化链接的操作,尽量放在函数之外,避免每次函数来临都要去初始化这样一个耗时的操作,我们可以利用函数的执行上下文重用,在启动环境执行代码时去初始化我们的数据库链接,例如 handler.js 头部的 require(’./model/db’)。
app/handler.js
require(‘dotenv’).config();
require(‘./model/db’);
const BooksModel = require(‘./model/books’);
const BooksController = require(‘./contrller/books’);
const booksController = new BooksController(BooksModel);
module.exports = {
create: event => booksController.create(event),
update: event => booksController.update(event),
find: () => booksController.find(),
deleteOne: event => booksController.deleteOne(event),
}
Serverless 配置文件
这个也是重点,plugins 插件的 serverless-offline 是为了本地调试用,functions 里面则定义了函数文件的路径和路由规则,注意如果是 /books/:id 这样的路由在 serverless.yml 里的路由规则为 books/{id}
service: mongodb-serverless-node-rest-api
provider:
name: aws
runtime: nodejs12.x
plugins:
functions:
create:
handler: app/handler.create
events:
path: books
method: post
update:
handler: app/handler.update
events:
path: books/{id}
method: put
find:
handler: app/handler.find
events:
path: books
method: get
deleteOne:
handler: app/handler.deleteOne
events:
path: books/{id}
method: delete
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
续更新**
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-7GLhSSe6-1712809122011)]
大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-2ZplE3HX-1712809122012)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。