[译] 用 Typescript + Node 配合 mongDB 写简单接口

2021-02-02 10:21:46 浏览数 (1)

写在最前面

  • 使用 node 完成一个 todolist appserver 端,其中包括基本的 ts 配置方案和完成了 Models 和 Controler 层。
  • 提示:需要对 Typescript 有一定了解,server 和 client 端均使用 Typescript
  • 默认已经安装好 yarn或者npm

您可以按照顺序阅读

  • 全栈 Todolist-server 篇 Node(server) React(client) MongoDB(database) Typescript
  • Todolist-database 篇(Cloud MongoDB)
  • Todolist-client 篇(React Typescript)

NodeJS App(server 端)

1、初始化(源码参考)
  • 新建文件夹
代码语言:javascript复制
mkdir server
cd server
  • 初始化
代码语言:javascript复制
yarn init
  • 构建文件目录
代码语言:javascript复制
├── dist
├── node_modules
├── src
   ├── app.ts
   ├── controllers
   |  └── todos
   |     └── index.ts
   ├── models
   |  └── todo.ts
   ├── routes
   |  └── index.ts
   └── types
      └── todo.ts
├── nodemon.json
├── package.json
├── tsconfig.json

app.ts 就是我们项目的入口,dist 文件夹主要是负责 ts 编译输出文件,nodemon.json 是数据库的配置项,后面会提到。

2、配置
  • 我们来配置 ts.config
代码语言:javascript复制
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "dist/js",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["src/types/*.ts", "node_modules", ".vscode"]
}

outDir: 告诉编译器,把编译好的 js 文件输出到 dist/js 目录

rootDir: ts 需要编译的根目录

include: 告诉编译器具体需要编译的地址.

exclude: 排除不需要编译的文章

  • 安装 typescript
代码语言:javascript复制
yarn add typescript -g
  • 安装 expressMongoDB 依赖和他们的 @types
代码语言:javascript复制
yarn add express cors mongoose

yarn add -D @types/node @types/express @types/mongoose @types/cors
  • 安装用来编译 Typescript 的concurrentlynodemon
代码语言:javascript复制
yarn add -D concurrently nodemon
  • 最后我们添加 build 和 start 脚本
代码语言:javascript复制
"scripts": {
    "build": "tsc",
    "start": "concurrently "tsc -w" "nodemon dist/js/app.js""
  }

ps:这里tsc 需要全局安装 ts 才能进行

  • concurrently 最主要的工作就是帮助我们编译 Typescript,进行热更新。
3、code(源码参考)
3.1 创建 todolist @types
  • types/todo.ts
代码语言:javascript复制
import { Document } from "mongoose"

export interface ITodo extends Document {
  name: string
  description: string
  status: boolean
}

创建的新的 @types 是来自 mongoose 的 Document,也就是基础的文本格式。

3.2 创建 todolist Model
  • models/todo.ts
代码语言:javascript复制
import { ITodo } from "./../types/todo"
import { model, Schema } from "mongoose"

const todoSchema: Schema = new Schema(
  {
    name: {
      type: String,
      required: true,
    },

    description: {
      type: String,
      required: true,
    },

    status: {
      type: Boolean,
      required: true,
    },
  },
  { timestamps: true }
)

export default model("Todo", todoSchema)

创建一个类型库定义 dotolist 的数据类型。

3.3 API controllers

现在我们在 controller 中添加几个 todolist 相关的方法。

getTodos
  • controllers/todos/index.ts
代码语言:javascript复制
import { Response, Request } from "express"
import { ITodo } from "./../../types/todo"
import Todo from "../../models/todo"

const getTodos = async (req: Request, res: Response): Promise<void> => {
  try {
    const todos: ITodo[] = await Todo.find()
    res.status(200).json({ todos })
  } catch (error) {
    throw error
  }
}

需要引入 express 来明确的定义我们的 response 和 request 类型。具体的解析如上,我们使用 json 来定义我们的数据。这个函数来初始化我们的 todolist 的数据,页面加载会调用。

addTodo
  • controllers/todos/index.ts
代码语言:javascript复制
const addTodo = async (req: Request, res: Response): Promise<void> => {
  try {
    const body = req.body as Pick"name" | "description" | "status">

    const todo: ITodo = new Todo({
      name: body.name,
      description: body.description,
      status: body.status,
    })

    const newTodo: ITodo = await todo.save()
    const allTodos: ITodo[] = await Todo.find()

    res
      .status(201)
      .json({ message: "Todo added", todo: newTodo, todos: allTodos })
  } catch (error) {
    throw error
  }
}

addTodo 函数用于添加新增一条的 list 和更新总的 lists。

updateTodo
  • controllers/todos/index.ts
代码语言:javascript复制
const updateTodo = async (req: Request, res: Response): Promise<void> => {
  try {
    const {
      params: { id },
      body,
    } = req
    const updateTodo: ITodo | null = await Todo.findByIdAndUpdate(
      { _id: id },
      body
    )
    const allTodos: ITodo[] = await Todo.find()
    res.status(200).json({
      message: "Todo updated",
      todo: updateTodo,
      todos: allTodos,
    })
  } catch (error) {
    throw error
  }
}

更新一条 list,变成完成状态。我们需要传相关的 id 确定具体的 list。

deleteTodo
  • controllers/todos/index.ts
代码语言:javascript复制
const deleteTodo = async (req: Request, res: Response): Promise<void> => {
    try {
        const deletedTodo: ITodo | null = await Todo.findByIdAndRemove(
            req.params.id
        );
        const allTodos: ITodo[] = await Todo.find();
        res.status(200).json({
            message: 'Todo deleted',
            todo: deletedTodo,
            todos: allTodos,
        });
    } catch (error) {
        throw error;
    }
};

删除一条信息

4、API routes
  • routes/index.ts
代码语言:javascript复制
import { Router } from "express"
import { getTodos, addTodo, updateTodo, deleteTodo } from "../controllers/todos"

const router: Router = Router()

router.get("/todos", getTodos)

router.post("/add-todo", addTodo)

router.put("/edit-todo/:id", updateTodo)

router.delete("/delete-todo/:id", deleteTodo)

export default router

好了现在基本的方法对应的路由就构建好了

5、MongoDB 数据库配置
  • nodemon.json
代码语言:javascript复制
{
    "env": {
        "MONGO_USER": "your-username",
        "MONGO_PASSWORD": "your-password",
        "MONGO_DB": "your-db-name"
    }
}

具体怎么配置?可以看我的这篇 mongoDB clound 云数据库的配置文章。

  • app.ts
代码语言:javascript复制
import express, { Express } from 'express';
import mongoose from 'mongoose';
import cors from 'cors';
import todoRoutes from './routes';
import bodyParser from 'body-parser';

const app: Express = express();

// 这里默认 4000 端口,后续 client 端会用到,如果想自定义,保持一致即可
const PORT: string | number = 4000;
// const PORT: string | number = process.env.PORT || 4000;

console.log(process.env.PORT);

app.use(cors()); // 跨域处理
app.use(bodyParser.json()); // post 请求处理
app.use(bodyParser.urlencoded({ extended: false }));
app.use(todoRoutes); // 咋们的 api 路由处理

const uri: string = `mongodb srv://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}@cluster0.4qpw4.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&w=majority`;

const options = { useNewUrlParser: true, useUnifiedTopology: true };
mongoose.set('useFindAndModify', false);

mongoose
    .connect(uri, options)
    .then(() =>
        app.listen(PORT, () =>
            console.log(`Server running on http://localhost:${PORT}`)
        )
    )
    .catch((error) => {
        throw error;
    });
复制代码

6、总结

  • ok,现在我们的 server 端和 clound database就完成了,下篇来介绍 client 端的构建。
  • 需要 gitignore的可以查看下面的 source code

7、源码

  • 源码参考
  • 大家可以按照 branch 分支的顺序查看

技术栈参考

  • 如果对上面技术栈不太熟悉的同学可以优先参考以下文档
    • react 官网
    • typescript 官网
    • node 官网
    • mongoDB 官网

翻译来自

  • freeCodeCamp

0 人点赞