目录规划

一个好的项目离不开一个好的目录规划,当然你也可以按照自己思路来做

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:

serverless-offline

functions:

create:

handler: app/handler.create

events:

http:

path: books

method: post

update:

handler: app/handler.update

events:

http:

path: books/{id}

method: put

find:

handler: app/handler.find

events:

http:

path: books

method: get

deleteOne:

handler: app/handler.deleteOne

events:

http:

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)]

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: