7-2 nodejs 之 Koa2 + MongoDB 简单开发

思考

开发一个 Web Server 需要考虑的点有:

1、接受请求,解析参数,解析方法类型

2、处理静态资源:缓存、存储等

3、连接、操作数据库

4、登录处理:session、cookie、token 等

5、api 的分层、参数过滤

6、拦截器的开发

7、mq(消息队列)处理、分布式架构

8、websocket、webrtc(音视频通话或 P2P 通信) 实时性

9、并发处理、事务处理(nodejs 弱项)

10、SSR 渲染前端页面

事务处理:白话来说就是一大堆有关联的操作的集合,若里面的任一操作有问题,则该事务就失败了,其中做了操作的还需要进行回滚。而 nodejs 本身对这块的实现很难,它是借助数据库来支持事务处理。

Express

官网文档:Express中文文档

核心是:异步串行流程控制

伪代码实现:

javascript 复制代码
const tasks = [
  function A(){
    // .....
    next()
  },
  function B(){
    // .....
    next()
  },

  // .....
  
  function X(){
    // .....
    next()
  }
]

function next(err, result) {
  if(err)  throw err
  
  var currentTask = tasks.shift()
  if(currentTask) currentTask(result)

  next() // 串行调用
}

// 首次调用
next()

Koa2 使用

官网:Koa | Koa中文文档 | Koa中文网

Koa 是一个很简洁的库,所以很多功能需要自己去找,在这里可以找:Koa 中间件

初始准备

  1. 新建个文件夹,然后初始化项目
kotlin 复制代码
mkdir koa2-actual-combat && cd koa2-actual-combat && pnpm init
  1. 安装 koa 依赖
csharp 复制代码
pnpm add koa
  1. 新建 src 文件夹与入口文件 && 安装 ip 依赖(可选)
bash 复制代码
mkdir src && touch src/server.js && pnpm add ip
  1. src/server.js编码
ini 复制代码
const Koa = require("koa");
const ip = require("ip");

const app = new Koa();

// 响应 - 中间件
app.use((ctx) => {
  ctx.body = "Hello Koa";
});

app.listen(3000, () => {
  console.log(
    `server is running: http://${ip.address()}:3000 or http://localhost:3000`
  );
});
  1. 命令行运行nodemon src/server.js,然后浏览器打开 http://localhost:3000 看效果

简单开发

完整线上项目代码:github.com/MrHzq/koa2-...

body 参数处理

  1. 安装 koa-bodyparser,用于将 string 类型的 body 参数转为 json 格式
sql 复制代码
pnpm add @koa/bodyparser
  1. 使用 @koa/bodyparser
javascript 复制代码
const Koa = require("koa");
const ip = require("ip");
const { bodyParser } = require("@koa/bodyparser"); // ++++++

const app = new Koa();

// koaBodyParser: 将 string 类型的 body 参数转为 json 格式 - 中间件
app.use(bodyParser()); // ++++++

// 响应 - 中间件
app.use((ctx) => {
  // ++++++ body 是放在 ctx.request.body 内的
  console.log("[ ctx.request.body ] >", ctx.request.body);
  ctx.body = "Hello Koa";
});

app.listen(3000, () => {
  console.log(
    `server is running: http://${ip.address()}:3000 or http://localhost:3000`
  );
});

路由处理

  1. 安装依赖@koa/router
sql 复制代码
pnpm add @koa/router
  1. 使用路由
ini 复制代码
const Koa = require("koa");
const ip = require("ip");
const { bodyParser } = require("@koa/bodyparser");
const Router = require("@koa/router");

const app = new Koa();

const router = new Router({ prefix: "/api" });

// koaBodyParser: 将 string 类型的 body 参数转为 json 格式 - 中间件
app.use(bodyParser());

router.get("/", (ctx) => {
  ctx.body = "helloworld";
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000, () => {
  console.log(
    `server is running: http://${ip.address()}:3000 or http://localhost:3000`
  );
});
  1. 路由封装
arduino 复制代码
mkdir

连接 Mongodb

  1. 安装mongoose依赖
csharp 复制代码
pnpm add mongoose
  1. 创建文件,写连接代码
javascript 复制代码
touch db.js

// 写如下代码:
// 1. 引入 mongodb 驱动包
const mongoose = require("mongoose");

const Connect = () => {
  // MongoDB 服务器的连接地址,其中可包含用户名、密码、域名、端口、数据库名等信息
  const DB_URL = "mongodb://127.0.0.1:27017/my-test";

  // 2. 建立连接
  mongoose.connect(DB_URL);

  /**
   * 连接成功 connected 数据库连接成功
   */
  mongoose.connection.on("connected", function () {
    console.log("Mongoose connection open to " + DB_URL);
  });

  /**
   * 连接异常 error 数据库连接错误
   */
  mongoose.connection.on("error", function (err) {
    console.log("Mongoose connection error: " + err);
  });
  /**
   * 连接断开 disconnected 连接异常断开
   */
  mongoose.connection.on("disconnected", function () {
    console.log("Mongoose connection disconnected");
  });
};

module.exports = Connect;
  1. 创建数据文件
bash 复制代码
mkdir models && touch models/other.js
  1. models/other.js写入代码
ini 复制代码
const mongoose = require("mongoose");

/**
 * 定义一个模式(相当于传统意义的表结构)
 * 每个模式映射mongoDB的一个集合,
 * 它定义(只是定义,不是实现)这个集合里面文档的结构,就是定义这个文档有什么字段,字段类型是什么,字段默认值是什么等。
 * 除了定义结构外,还定义文档的实例方法,静态模型方法,复合索引,中间件等
 * @type {mongoose}
 */
const OtherSchema = new mongoose.Schema(
  //数据为表头数据列
  {
    username: String,
    password: String,
  }
);

const collationName = "Other"; // 集合名,相当于表名,一定要大写
const Other = mongoose.model(collationName, OtherSchema); // 当没有该集合时,自动创建该集合

module.exports = Other

5、server.js引入数据库相关

php 复制代码
const Koa = require("koa");
const ip = require("ip");
const { bodyParser } = require("@koa/bodyparser");
const Router = require("@koa/router");

const MongooseConnect = require("./db"); // ++++++
MongooseConnect(); // ++++++

const { Other } = require("./models/other"); // ++++++

const app = new Koa();

const router = new Router({ prefix: "/api" });

// koaBodyParser: 将 string 类型的 body 参数转为 json 格式 - 中间件
app.use(bodyParser());

router.get("/", (ctx) => {
  ctx.body = "helloworld";
});

// ++++++
router.post("/other/create", async (ctx) => {
  const { username, password } = ctx.request.body;
  const res = await Other.create({ username, password });
  ctx.body = {
    status: 200,
    msg: "success",
    data: res,
  };
});

// ++++++
router.get("/other/list", async (ctx) => {
  const res = await Other.findOne();
  ctx.body = {
    status: 200,
    msg: "success",
    data: res || ["default"],
  };
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000, () => {
  console.log(
    `server is running: http://${ip.address()}:3000 or http://localhost:3000`
  );
});
  1. 浏览器打开:http://localhost:3000/api/other/list
  1. 调用接口,插入数据

mac M1 电脑安装 mongodb

mongod 是用来连接到 mongodb 数据库服务器的,即服务器端。

mongo 是用来启动 MongoDB shell 的,是 mongodb 的命令行客户端

brew 安装流程(首推方式)

(可选)1、查看 xcode-select 版本,没有的话就需要安装

csharp 复制代码
xcode-select -v

xcode-select --install // 安装命令

(可选)2、查看 brew 版本,没有的话就需要安装

bash 复制代码
brew -v

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" // 安装命令

3、安装为 MongoDB 定制的 Homebrew tap

arduino 复制代码
 brew tap mongodb/brew

// 安装完后,查看情况:
brew tap

// caskroom/cask
// homebrew/cask
// homebrew/core
// homebrew/services
// mongodb/brew

4、更新 brew

sql 复制代码
brew update

5、安装 MongoDB 5.0 社区版

css 复制代码
brew install mongodb-community@5.0

/opt/homebrew下:/var/mongodb内存放了相关的数据;/var/log/mongodb内存放了相关的日志

运行echo 'export PATH="/opt/homebrew/opt/mongodb-community@5.0/bin:$PATH"' >> ~/.zshrc将其注入环境变量,然后再source ~/.zshrc一下,就可以使用mongo、mongod命令了

6、启动 mongodb

sql 复制代码
brew services start mongodb-community@5.0

7、查看启动情况

brew services list

并且浏览器可打开:http://127.0.0.1:27017 查看

8、停止 mongodb

arduino 复制代码
brew services stop mongodb-community@5.0

压缩包安装流程(次推方式)

流程比较麻烦,brew 安装不成功时可以用这种方式

1、去官网下载压缩包:www.mongodb.com/try/downloa...

2、解压下载的压缩包,解压后如下

3、进入/usr/local,打开在"访达",快捷键:cmd+shift+g,输入/usr/local

4、新建文件夹mongodb,然后将解压后里面的所有文件拷贝过来

5、配置环境变量,打开你的.bash_profile or .zshrc

arduino 复制代码
open -e ~/.bash_profile
// or
open -e ~/.zshrc

5.1、最末尾输入下面配置,我的是.zshrc,然后保存并关闭

bash 复制代码
export PATH="$PATH:/usr/local/mongodb/bin"

6、然后任意打开终端,输入source ~/.bash_profileorsource ~/.zshrc

7、终端内继续输入mongod -version,正常情况可以看到有打印

8、若出现异常情况,比如提示xxx不安全,则"访达"进入/usr/local/mongodb/bin文件夹,找到mongod,然后右键 -> 打开,之后一路都点ok

9、第 8 步完成后,再次进行第 7 步

10、找个目录,新建存放数据与日志的文件夹

11、更改文件读写权限,打开任意终端,直接输入下面的命令,需要输入你的电脑密码

bash 复制代码
sudo chown -R $(whoami) /Users/hzq/sqldata/mongodb/data
sudo chown -R $(whoami) /Users/hzq/sqldata/mongodb/log

12、启动 mongodb,打开任意终端,输入下面的命令

c 复制代码
mongod --dbpath /Users/hzq/sqldata/mongodb/data --logpath /Users/hzq/sqldata/mongodb/log/mongo.log

// --dbpath 设置数据存放目录
// --logpath 设置日志存放目录

13、查看启动情况:打开任意终端,输入下面的命令,看到启动的进程 ID 是 34030

perl 复制代码
ps aux | grep -v grep | grep mongod

14、查看启动情况:浏览器打开 http://127.0.0.1:27017,看到这个说明启动成功

15、停止服务,直接终端内conrtol + c可终止

16、若无法终止,可终端输入下面的命令

arduino 复制代码
// 简单高效
kill mongod_PID // 我的是 kill 34030

可视化工具

官方工具(推荐安装)

不支持 SQL 查询

1、下载官方工具:官网下载地址,然后安装、打开,进入主页面

2、连接(先命令行启动 mongodb 哦)

3、连接后长这个样子

其他工具

NoSQLBooster(推荐安装)

支持 SQL 查询

1、NoSQLBooster 下载地址:官网下载地址,然后安装、打开,进入主页面

2、连接

MongoDB for VS Code

VScode 插件

1、安装插件,创建连接,效果如下:

mongodb 增删改查(TODO)

相关推荐
神夜大侠32 分钟前
VUE 实现公告无缝循环滚动
前端·javascript·vue.js
明辉光焱35 分钟前
【Electron】Electron Forge如何支持Element plus?
前端·javascript·vue.js·electron·node.js
柯南二号1 小时前
HarmonyOS ArkTS 下拉列表组件
前端·javascript·数据库·harmonyos·arkts
wyy72931 小时前
v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条
前端·ui·html
前端郭德纲1 小时前
ES6的Iterator 和 for...of 循环
前端·ecmascript·es6
王解1 小时前
【模块化大作战】Webpack如何搞定CommonJS与ES6混战(3)
前端·webpack·es6
欲游山河十万里1 小时前
(02)ES6教程——Map、Set、Reflect、Proxy、字符串、数值、对象、数组、函数
前端·ecmascript·es6
明辉光焱1 小时前
【ES6】ES6中,如何实现桥接模式?
前端·javascript·es6·桥接模式
PyAIGCMaster2 小时前
python环境中,敏感数据的存储与读取问题解决方案
服务器·前端·python
baozhengw2 小时前
UniAPP快速入门教程(一)
前端·uni-app