Deno 是一个现代化的 JavaScript 和 TypeScript 运行时,用于构建服务器端应用程序和命令行工具。与 Node.js 不同,Deno 采用了安全性高的设计,不仅仅就是安全上多了很多可以控制的函数,而且还可以利用现有的 ES 模块库,省去了一些研究或配置工作。在这篇文章中,我们将介绍如何使用 Deno 来构建一个基于 RESTful API 的应用程序。
RESTful API 简介
RESTful API 是一种 Web API 设计风格,它使用 HTTP 协议的 GET、POST、PUT、DELETE 等方法来对数据进行操作,通常返回 JSON 格式的数据响应。RESTful API 成为了主流的 API 设计风格,并广泛应用于互联网开发和移动应用程序领域。
如何使用 Deno 实现 RESTful API
Deno 的标准库中包含了许多有用的 API,可以轻松地构建 Web 应用程序,比如 Deno 自带的 http 模块可以实现网络请求和响应的功能。在这篇文章中,我们将使用 Deno 来创建一个基于 RESTful API 的 TODO 应用程序,我们将使用 Deno 随附的 http 模块来处理 HTTP 请求。
1. 创建项目
首先,在本地的开发环境中安装 Deno,可以使用以下命令:
$ curl -fsSL https://deno.land/x/install/install.sh | sh
在安装完成后,你可以在命令行窗口中输入以下命令,检查 Deno 是否安装成功:
$ deno --version
接下来,我们可以创建一个新的项目,在项目文件夹中创建 app.js 文件:
$ mkdir todo-api && cd todo-api $ touch app.js
2. 初始化依赖
在项目文件夹中创建 deps.ts 文件,在这个文件中添加 http 模块的依赖:
// deps.ts
export {
ServerRequest,
serve,
Response,
Status,
} from "https://deno.land/std/http/mod.ts";接下来,我们创建一个 mod.ts 文件,该文件将在启动应用程序时加载,可以将其看作是应用程序的入口点。在 mod.ts 文件中,我们将导入我们的 app.ts 文件:
// www.javascriptcn.com code example
// mod.ts
import { serve } from "./deps.ts";
import { app } from "./app.ts";
const server = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const request of server) {
app.handle(request);
}3. 创建 TODO 控制器
我们将创建一个 controllers/todo-controller.ts 文件来处理 TODO 事项。在这个文件中,我们将定义一个 TodoController 类,该类将封装所有 CRUD 操作:
// www.javascriptcn.com code example
// controllers/todo-controller.ts
import { Response } from "../deps.ts";
interface ITodo {
id: string;
title: string;
completed: boolean;
}
class TodoController {
todos: ITodo[] = [];
constructor() {
this.todos = [
{
id: "1",
title: "Buy Milk",
completed: true,
},
{
id: "2",
title: "Learn Deno",
completed: false,
},
];
}
async getTodos(): Promise<Response> {
return {
body: JSON.stringify(this.todos),
};
}
async getTodoById(id: string): Promise<Response> {
const todo = this.todos.find((t) => t.id === id);
if (!todo) {
return {
status: 404,
body: JSON.stringify({
message: `Todo with id ${id} not found`,
}),
};
}
return {
body: JSON.stringify(todo),
};
}
async createTodo(
request: Request,
): Promise<Response> {
const { title } = await request.json();
const newTodo: ITodo = {
id: Math.floor(Math.random() * 1000).toString(),
title,
completed: false,
};
this.todos.push(newTodo);
return {
body: JSON.stringify(newTodo),
};
}
async updateTodo(
id: string,
request: Request,
): Promise<Response> {
const todo = this.todos.find((t) => t.id === id);
if (!todo) {
return {
status: 404,
body: JSON.stringify({
message: `Todo with id ${id} not found`,
}),
};
}
const { title, completed } = await request.json();
todo.title = title;
todo.completed = completed;
return {
body: JSON.stringify(todo),
};
}
async deleteTodo(id: string): Promise<Response> {
const todoIndex = this.todos.findIndex((t) => t.id === id);
if (todoIndex === -1) {
return {
status: 404,
body: JSON.stringify({
message: `Todo with id ${id} not found`,
}),
};
}
this.todos.splice(todoIndex, 1);
return {
body: JSON.stringify({
message: `Todo with id ${id} deleted successfully`,
}),
};
}
}
export const todoController = new TodoController();4. 创建应用程序
我们将定义一个 app.ts 文件,该文件将使用 TodoController 类来管理 TODO 事项。在 app.ts 文件中,我们将定义一个 handleRequest 函数,该函数将处理所有 HTTP 请求。
// www.javascriptcn.com code example
// app.ts
import { ServerRequest, Response } from "./deps.ts";
import { todoController } from "./controllers/todo-controller.ts";
interface Route {
method: string;
path: string;
handler: (
request: Request,
params: Record<string, string>,
) => Promise<Response>;
}
class Router {
private routes: Route[] = [];
add(route: Route): void {
this.routes.push(route);
}
match(request: Request): Route | undefined {
const url = new URL(request.url);
const path = url.pathname;
return this.routes.find((route) => {
const routePath = route.path.replace(/:[\w\d]+/g, "([\\w\\d]+)");
const regex = new RegExp(`^${routePath}$`);
const params = {};
const matched = path.match(regex);
if (matched) {
const matches = matched.slice(1);
const paramNames = route.path.match(/:[\w\d]+/g) || [];
paramNames.forEach((name, index) => {
params[name.slice(1)] = matches[index];
});
request.params = params;
return true;
}
return false;
});
}
}
const router = new Router();
router.add({
method: "GET",
path: "/todos",
handler: todoController.getTodos.bind(todoController),
});
router.add({
method: "GET",
path: "/todos/:id",
handler: (request, params) =>
todoController.getTodoById(params.id),
});
router.add({
method: "POST",
path: "/todos",
handler: todoController.createTodo.bind(todoController),
});
router.add({
method: "PUT",
path: "/todos/:id",
handler: (request, params) =>
todoController.updateTodo(params.id, request),
});
router.add({
method: "DELETE",
path: "/todos/:id",
handler: (request, params) =>
todoController.deleteTodo(params.id),
});
export const app = {
handle: async (request: ServerRequest): Promise<void> => {
const route = router.match(request);
if (!route) {
request.respond({
status: 404,
body: JSON.stringify({
message: `Not found`,
}),
});
return;
}
const response = await route.handler(request, request.params);
request.respond({
status: response.status,
body: response.body,
});
},
};5. 测试应用程序
现在,我们已经完成了我们的应用程序,让我们启动它并测试它:
$ deno run --allow-net mod.ts
在命令行窗口中输入以上命令,我们的应用程序将在 8000 端口上启动。你可以在浏览器中输入 http://localhost:8000/todos,将显示所有的 TODO 事项。你也可以使用 POSTMAN 或 CURL 等工具测试获取、添加、更新和删除 TODO 事项的 RESTful API。
综上所述,本文简要介绍了 Deno 和 RESTful API,并详细说明了如何使用 Deno 创建一个基于 RESTful API 的 TODO 应用程序。这个项目可以帮助初学者了解和学习 Deno 中如何使用 HTTP 模块来处理 HTTP 请求和响应,以及如何使用 RESTful API 设计模式来创建 Web API。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67cfc72ee46428fe9ebbe468