deno使用rust

I recently wrote about how to make a Todo API in Deno + Oak (without using a database). You can find the repo under chapter_1:oak on GitHub.

我最近写了关于如何在Deno + Oak(不使用数据库)中制作Todo API的文章 。 您可以在GitHub上的Chapter_1:oak下找到该存储库。

This tutorial picks up where the other left off, and I'll go over how to integrate MySQL into a Deno and Oak project.

本教程从另一个地方开始,继续学习如何将MySQL集成到Deno和Oak项目中。

If at any time you want to see the entire source code used in this tutorial, it's available at chapter_2:mysql. Feel free to give it a star on GitHub if you like it.

如果您想随时查看本教程中使用的全部源代码,可以在Chapter_2:mysql上找到 。 如果愿意,可以在GitHub上给它加星号。

I'm assuming that you already completed the last tutorial mentioned above. If not, check it out here and come back when you're finished.

我假设您已经完成了上述最后一个教程。 如果没有,请在此处查看并在完成后再返回。

Before we start, make sure that you have a MySQL client installed and running:

在开始之前,请确保您已安装并正在运行MySQL客户端:

  • MySQL community server [Download here]

    MySQL社区服务器[ 在此处下载 ]

  • MySQL Workbench [Download here]

    MySQL Workbench [ 在这里下载 ]

I wrote a small guide for Mac OS users on setting up MySQL because I struggled with it as well. Check it out here.

我为Mac OS用户写了一个关于设置MySQL的小指南,因为我也很努力。 在这里查看 。

If you are on a Windows machine you can use the same tools or you can also use XAMPP to have a MySQL instance running in your dashboard.

如果您使用的是Windows计算机,则可以使用相同的工具,也可以使用XAMPP在仪表板上运行MySQL实例。

Once you have a MySQL instance running we can begin our tutorial.

一旦您运行了MySQL实例,就可以开始我们的教程。

让我们开始 (Let's Begin)

Assuming that you're coming from this article, Todo API in Deno + Oak (without using a database), we will do the following:

假设您来自Deno + Oak中的Todo API(不使用数据库) ,我们将执行以下操作:

  • Create a MySQL database connection创建一个MySQL数据库连接
  • Write a small script that resets the database every time we start our Deno server编写一个小脚本,每次启动Deno服务器时都会重置数据库
  • Perform CRUD operations on a table在表上执行CRUD操作
  • Add the CRUD functionality to our API controllers将CRUD功能添加到我们的API控制器中

One last thing – here is the entire commit difference that was made in Chapter 1 to add MySQL to the project (source code that shows the new additions made from chapter 1).

最后一件事–这是在第1章中将MySQL添加到项目中的整个提交差异( 源代码显示了第1章中新增的内容 )。

In your project root folder – mine is called chapter_2:mysql, though yours can be called whatever you want – create a folder called db. Inside that folder, create a file called config.ts and add the following content to it:

在您的项目根文件夹中-我的被称为chapter_2:mysql 您的名字可以随心所欲–创建一个名为db的文件夹。 在该文件夹中,创建一个名为config.ts的文件, 并向其中添加以下内容:

export const DATABASE: string = "deno";
export const TABLE = {TODO: "todo",
};

Nothing fancy here, just defining our database name along with an object for tables and then exporting it. Our project will have one database called "deno" and inside that db we will only have one table called "todo".

这里没有什么幻想,只需定义我们的数据库名称以及用于表的对象,然后将其导出即可。 我们的项目将有一个名为“ deno”的数据库,在该数据库内,我们将只有一个名为“ todo”的表。

Next, inside the db folder, create another file called client.ts and add the following content:

接下来,在db文件夹中,创建另一个名为client.ts的文件,并添加以下内容:

import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";const client = await new Client();client.connect({hostname: "127.0.0.1",username: "root",password: "",db: "",
});export default client;

A couple of things are happening here.

这里发生了几件事。

We are importing Client from the mysql library. Client will help us connect to our database and perform operations in the database.

我们正在从mysql库导入ClientClient将帮助我们连接到数据库并在数据库中执行操作。

client.connect({hostname: "127.0.0.1",username: "root",password: "",db: "",
});

Client provides a method called connect which takes in object where we can provide the hostname, username, password, and db. With this information it can establish a connection to our MySQL instance.

Client提供了一种名为connect的方法,该方法接受对象,我们可以在其中提供hostnameusernamepassworddb 。 利用此信息,它可以建立与我们MySQL实例的连接。

Make sure that your username has no password, as it will conflict with connecting to Deno's MySQL library. If you don't know on how to do that, read this tutorial I wrote.

确保您的username没有password ,因为它会与连接到DenoMySQL库冲突。 如果您不知道该怎么做,请阅读我写的本教程 。

I have left the database field blank here because I want to select it manually later in my script.

我在此处将database字段留空,因为我想稍后在脚本中手动选择它。

Let's add a script that will initialize a database called "deno", select it, and inside that db create a table called "todo".

让我们添加一个脚本,该脚本将初始化一个名为“ deno”的数据库,将其选中,然后在该数据库内部创建一个名为“ todo”的表。

Inside db/client.ts file let's make some new additions:

db/client.ts文件中,我们添加了一些新内容:

import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";const client = await new Client();client.connect({hostname: "127.0.0.1",username: "root",password: "",db: "",
});const run = async () => {// create database (if not created before)await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);// select dbawait client.execute(`USE ${DATABASE}`);// delete table if it exists beforeawait client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);// create tableawait client.execute(`CREATE TABLE ${TABLE.TODO} (id int(11) NOT NULL AUTO_INCREMENT,todo varchar(100) NOT NULL,isCompleted boolean NOT NULL default false,PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8;`);
};run();export default client;

Here we are importing DATABASE and TABLE from our config file, then using those values in a new function called run().

在这里,我们从配置文件中导入DATABASETABLE ,然后在名为run()的新函数中使用这些值。

Let's break down this run() function. I have added comments in the file to help you understand the workflow:

让我们分解一下run()函数。 我在文件中添加了注释,以帮助您了解工作流程:

const run = async () => {// create database (if not created before)await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);// select dbawait client.execute(`USE ${DATABASE}`);// delete table if it exists beforeawait client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);// create tableawait client.execute(`CREATE TABLE ${TABLE.TODO} (id int(11) NOT NULL AUTO_INCREMENT,todo varchar(100) NOT NULL,isCompleted boolean NOT NULL default false,PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8;`);
};run();
  • Create a database called deno . If it already exists then do nothing.

    创建一个名为deno的数据库。 如果已经存在,则什么也不做。

  • Then select the database to use, which is called deno

    然后选择要使用的数据库,称为deno

  • Delete the table inside deno called todo if it already exists.

    删除表内denotodo如果它已经存在。

  • Next, create a new table inside the deno db, call it todo, and define its structure: It will have a unique auto increment id which will be an integer, another field called todo which will be a string, and finally a field called isCompleted which is a boolean. I also define id as my primary key.

    接下来,在deno db内创建一个新表,将其称为todo ,并定义其结构:它将具有唯一的自动增量id (将是整数),另一个名为todo字段(将是字符串)以及最后一个名为isCompleted的字段这是一个布尔值。 我还将id定义为主键。

The reason I wrote this script was because I don't want to have extra information in MySQL instance. Every time the script runs it just reinitializes everything.

我写这个脚本的原因是因为我不想在MySQL实例中获得更多信息。 每次脚本运行时,它都会重新初始化所有内容。

You don't have to add this script. But if you don't, then you will have to manually create a db and the table.

您不必添加此脚本。 但是,如果不这样做,则必须手动创建数据库和表。

Also, check out the Deno MySQL library's docs on db creation and on table creation.

另外,查看有关数据库创建和表创建的Deno MySQL库的文档。

Going back to our agenda, we just achieved two things out of the four mentioned at the top of the article:

回到我们的议程,我们在文章顶部提到的四件事中仅实现了两件事:

  • Create a MySQL database connection创建一个MySQL数据库连接
  • Write a small script that resets the database every time we start our Deno server编写一个小脚本,每次启动Deno服务器时都会重置数据库

That is already 50% of the tutorial. Unfortunately, we can't see much happening right now. Let's quickly add some functionality to see it working.

那已经是本教程的50%。 不幸的是,我们现在看不到太多事情发生。 让我们快速添加一些功能以使其正常运行。

在表上执行CRUD操作并将功能添加到我们的API控制器 (Performing CRUD operations on a table and adding the functionality to our API controllers)

We need to update our Todo interface first. Go to the interfaces/Todo.ts file and add the following:

我们需要先更新Todo界面。 转到interfaces/Todo.ts文件并添加以下内容:

export default interface Todo {id?: number,todo?: string,isCompleted?: boolean,
}

What this ? does is it makes the key in the object optional. I did this because later I will use different functions to pass objects with only an id, todo, isCompleted, or all of them at once.

这是什么? 它的作用是使对象中的键成为可选键。 我这样做是因为稍后我将使用不同的函数来传递仅具有idtodoisCompleted或所有这些对象的对象。

If you want to learn more about optional properties in TypeScript, head over to their docs here.

如果您想了解有关TypeScript中可选属性的更多信息,请访问此处的文档。

Next, create a new folder called models and inside that folder, create a file called todo.ts. Add the following content to the file:

接下来,创建一个名为models的新文件夹,并在该文件夹内创建一个名为todo.ts的文件。 将以下内容添加到文件中:

import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";export default {/*** Takes in the id params & checks if the todo item exists* in the database* @param id* @returns boolean to tell if an entry of todo exits in table*/doesExistById: async ({ id }: Todo) => {},/*** Will return all the entries in the todo column* @returns array of todos*/getAll: async () => {},/*** Takes in the id params & returns the todo item found* against it.* @param id* @returns object of todo item*/getById: async ({ id }: Todo) => {},/*** Adds a new todo item to todo table* @param todo* @param isCompleted*/add: async ({ todo, isCompleted }: Todo,) => {},/*** Updates the content of a single todo item* @param id* @param todo* @param isCompleted* @returns integer (count of effect rows)*/updateById: async ({ id, todo, isCompleted }: Todo) => {},/*** Deletes a todo by ID* @param id* @returns integer (count of effect rows)*/deleteById: async ({ id }: Todo) => {},
};

Right now the functions are empty, but that is okay. We will fill them up one by one.

现在函数是空的,但是没关系。 我们将一一填写。

Next go to controllers/todo.ts file and make sure you add the following:

接下来转到controllers/todo.ts文件,并确保添加以下内容:

// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";export default {/*** @description Get all todos* @route GET /todos*/getAllTodos: async ({ response }: { response: any }) => {},/*** @description Add a new todo* @route POST /todos*/createTodo: async ({ request, response }: { request: any; response: any },) => {},/*** @description Get todo by id* @route GET todos/:id*/getTodoById: async ({ params, response }: { params: { id: string }; response: any },) => {},/*** @description Update todo by id* @route PUT todos/:id*/updateTodoById: async ({ params, request, response }: {params: { id: string };request: any;response: any;},) => {},/*** @description Delete todo by id* @route DELETE todos/:id*/deleteTodoById: async ({ params, response }: { params: { id: string }; response: any },) => {},
};

Here we have empty functions as well. Let's start filling them up.

在这里,我们还有空函数。 让我们开始填充它们。

[获取]所有待办事项API ([Get] all todos API)

Inside models/todo.ts, add a definition for a function called getAll:

models/todo.ts内部,添加一个名为getAll的函数的定义:

The Client also exposes another method besides connect (we used a "connect" method in db/client.ts file) and that is query. The client.query method lets us run MySQL queries directly from our Deno code as is.

Client还公开了connect以外的另一种方法(我们在db/client.ts文件中使用了“ connect”方法),即query 。 通过client.query方法,我们可以直接从Deno代码直接运行MySQL查询。

Next go to controllers/todo.ts add definition for getAllTodos:

接下来转到controllers/todo.tsgetAllTodos添加定义:

// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";export default {/*** @description Get all todos* @route GET /todos*/getAllTodos: async ({ response }: { response: any }) => {try {const data = await TodoModel.getAll();response.status = 200;response.body = {success: true,data,};} catch (error) {response.status = 400;response.body = {success: false,message: `Error: ${error}`,};}},
}

All we are doing is importing TodoModel and using its method called getAll, which we just defined now. Since it returns as a promise we have wrapped it in async/await.

我们要做的就是导入TodoModel并使用我们刚刚定义的名为getAll方法。 由于它作为承诺返回,因此我们将其包装在async / await中。

The method TodoModel.getAll() will return us an array which we simply return to response.body with status set to 200.

方法TodoModel.getAll()将为我们返回一个数组,我们只需将其返回status200 response.body即可。

If the promise fails or there is another error, we simply go to our catch block and return a status of 400 with success set to false. We also set the message to what we get from the catch block.

如果诺言失败或存在其他错误,我们只需转到catch块并返回400且success设置为false的状态。 我们还将message设置为我们从catch块获得的message

That's it, we're done. Now let's fire up our terminal.

就是这样,我们完成了。 现在让我们启动终端。

Make sure your MySQL instance is running. In your terminal type:

确保您MySQL实例正在运行。 在您的终端中输入:

$ deno run --allow-net server.ts

Your terminal should look something like this:

您的终端应如下所示:

My console is telling me two things here.

我的控制台在这里告诉我两件事。

  1. That my Deno API server is running on port 8080我的Deno API服务器正在端口8080上运行
  2. That my MySQL instance is running on 127.0.0.1, which is localhost

    我MySQL实例在127.0.0.1上运行,它是localhost

Let's test our API out. I am using Postman here, but you can use your favorite API client.

让我们测试一下我们的API。 我在这里使用Postman ,但您可以使用自己喜欢的API客户端。

Right now it only returns empty data. But once we add data to our todo table, it will return those todos here.

现在,它仅返回空数据。 但是,一旦我们将数据添加到todo表中,它将在此处返回这些todo

Awesome. One API down and four more to go.

太棒了 减少了一个API,还有四个API。

[发布]添加待办事项API ([Post] add a todo API)

In the models/todo.ts file, add the following definition for add() function:

models/todo.ts文件中,为add()函数添加以下定义:

export default {/*** Adds a new todo item to todo table* @param todo* @param isCompleted*/add: async ({ todo, isCompleted }: Todo,) => {return await client.query(`INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,[todo,isCompleted,],);},
}

The add function takes in object as an argument, which has two items: todo and isCompleted.

add函数将object作为参数,它具有两项: todoisCompleted

So add: async ({ todo, isCompleted }: Todo) => {} can also be written as ({todo, isCompleted}: {todo:string, isCompleted:boolean}). But since we already have an interface defined in our interfaces/Todo.ts file which is

因此add : async ({ todo, isCompleted }: Todo) => {}也可以写成({todo, isCompleted}: {todo:string, isCompleted:boolean}) 。 但是由于我们已经在interfaces/Todo.ts文件中定义了一个接口,因此

export default interface Todo {id?: number,todo?: string,isCompleted?: boolean,
}

we can simply write this as add: async ({ todo, isCompleted }: Todo) => {}. This tells TypeScript that this function has two arguments, todo, which is a string, and isCompleted, which is a boolean.

我们可以简单地将其写为add : async ({ todo, isCompleted }: Todo) => {} 。 这告诉TypeScript该函数有两个参数,分别是字符串todo和一个布尔值isCompleted

If you want to read more on interfaces, TypeScript has an excellent document on it which you can find here.

如果您想阅读有关接口的更多信息,TypeScript上有一个很好的文档,您可以在这里找到。

Inside our function we have the following:

在我们的函数中,我们具有以下内容:

return await client.query(`INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,[todo,isCompleted,],
);

This query can be broken down into two parts:

该查询可以分为两部分:

  • INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?). The two question marks here denote a use of variables inside this query.

    INSERT INTO ${TABLE . TODO}(todo, isCompleted) values(?, ?) INSERT INTO ${TABLE . TODO}(todo, isCompleted) values(?, ?) 。 这里的两个问号表示此查询中变量的使用。

  • The other part, [todo, isCompleted], is the variables that will go in the first part of the query and be replaced with (?, ?)

    另一部分[todo, isCompleted]是将在查询的第一部分中被并替换为(?, ?)的变量(?, ?)

  • Table.Todo is just a string coming from file db/config.ts where the Table.Todo value is "todo"

    Table.Todo只是来自文件db/config.ts的字符串,其中Table.Todo值为“ todo

Next inside our controllers/todo.ts file, go to the definition of the createTodo() function:

接下来在我们的controllers/todo.ts文件中,转到createTodo()函数的定义:

export default {/*** @description Add a new todo* @route POST /todos*/createTodo: async ({ request, response }: { request: any; response: any },) => {const body = await request.body();if (!request.hasBody) {response.status = 400;response.body = {success: false,message: "No data provided",};return;}try {await TodoModel.add({ todo: body.value.todo, isCompleted: false },);response.body = {success: true,message: "The record was added successfully",};} catch (error) {response.status = 400;response.body = {success: false,message: `Error: ${error}`,};}},
}

Let's break this down into two parts:

让我们将其分为两部分:

Part 1

第1部分

const body = await request.body();
if (!request.hasBody) {response.status = 400;response.body = {success: false,message: "No data provided",};return;
}

All we are doing here is checking if the user is sending data in body. If not, then we return a status 400 and in the body return success: false and message: <erromessage-string>.

我们在这里所做的只是检查用户是否在体内发送数据。 如果不是,则返回状态400 ,然后在正文中返回success: falsemessage: <erromessage-string>

Part 2

第2部分

try {await TodoModel.add({ todo: body.value.todo, isCompleted: false },);response.body = {success: true,message: "The record was added successfully",};
} catch (error) {response.status = 400;response.body = {success: false,message: `Error: ${error}`,};
}

If there is no error, the TodoModel.add() function is called and simply returns a status of 200 and a confirmation message to the user.

如果没有错误,则TodoModel.add()函数,并简单地向用户返回状态200和确认消息。

Otherwise it just throws a similar error that we did in the previous API.

否则,它只会引发与之前的API类似的错误。

Now we're done. Fire up your terminal and make sure your MySQL instance is running. In your terminal type:

现在我们完成了。 启动您的终端,并确保您MySQL实例正在运行。 在您的终端中输入:

$ deno run --allow-net server.ts

Go to Postman and run the API route for this controller:

转到Postman并为此控制器运行API路由:

This is great, now we have two working APIs. Only three more to go.

太好了,现在我们有两个有效的API。 仅剩三个。

[GET]通过ID API执行 ([GET] todo by id API)

In your models/todo.ts file, add definition for these two functions, doesExistById() and getById():

在你的models/todo.ts文件,添加定义这两个功能, doesExistById()getById()

export default {/*** Takes in the id params & checks if the todo item exists* in the database* @param id* @returns boolean to tell if an entry of todo exits in table*/doesExistById: async ({ id }: Todo) => {const [result] = await client.query(`SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,[id],);return result.count > 0;},/*** Takes in the id params & returns the todo item found* against it.* @param id* @returns object of todo item*/getById: async ({ id }: Todo) => {return await client.query(`SELECT * FROM ${TABLE.TODO} WHERE id = ?`,[id],);},
}

Let's talk about each function one by one:

让我们一一讨论每个功能:

  • doesExistById takes in an id and returns a boolean indicating whether a particular todo exists in the database or not.

    doesExistById接受一个id并返回一个boolean ,该boolean指示数据库中是否存在特定的待办事项。

Let's break this function down:

让我们分解一下这个功能:

const [result] = await client.query(`SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,[id],
);
return result.count > 0;

We simply check the count here in the table against a particular todo id. If the count is greater than zero, we return true. Otherwise, we return false.

我们只需要对照特定的待办事项ID检查表中的计数。 如果计数大于零,则返回true 。 否则,我们返回false

  • getById returns the todo item against a particular id:

    getById返回针对特定ID的待办事项:

return await client.query(`SELECT * FROM ${TABLE.TODO} WHERE id = ?`,[id],
);

We are simply running a MySQL query here to get a todo by id and returning the result as-is.

我们只是在这里运行一个MySQL查询,以通过id获取待办事项并按原样返回结果。

Next, go to your controllers/todo.ts file and add a definition for a getTodoById controller method:

接下来,转到您的controllers/todo.ts文件,并为getTodoById控制器方法添加定义:

export default {/*** @description Get todo by id* @route GET todos/:id*/getTodoById: async ({ params, response }: { params: { id: string }; response: any },) => {try {const isAvailable = await TodoModel.doesExistById({ id: Number(params.id) },);if (!isAvailable) {response.status = 404;response.body = {success: false,message: "No todo found",};return;}const todo = await TodoModel.getById({ id: Number(params.id) });response.status = 200;response.body = {success: true,data: todo,};} catch (error) {response.status = 400;response.body = {success: false,message: `Error: ${error}`,};}},
}

Let's break this down into two smaller parts:

让我们将其分为两个较小的部分:

const isAvailable = await TodoModel.doesExistById({ id: Number(params.id) },
);if (!isAvailable) {response.status = 404;response.body = {success: false,message: "No todo found",};return;
}

First we check if the todo exists in the database against an id by using this method:

首先,我们使用此方法根据ID检查待办事项是否存在于数据库中:

const isAvailable = await TodoModel.doesExistById({ id: Number(params.id) },
);

Here we need to convert params.id into a Number because our todo interface only accepts id as a number. Next, we just pass params.id to the doesExistById method. This method will return as a boolean.

这里我们需要将params.id转换为Number因为我们的todo接口仅接受id作为数字。 接下来,我们仅将params.id传递给doesExistById方法。 此方法将以布尔值形式返回。

Then we simply check if the todo is not available and return a 404 method with our standard response like with the previous endpoints:

然后,我们只需检查待办事项是否不可用,并使用我们的标准响应(如先前的端点)返回404方法:

if (!isAvailable) {response.status = 404;response.body = {success: false,message: "No todo found",};return;
}

Then we have:

然后我们有:

try {
const todo: Todo = await TodoModel.getById({ id: Number(params.id) });
response.status = 200;
response.body = {success: true,data: todo,
};
} catch (error) {
response.status = 400;
response.body = {success: false,message: `Error: ${error}`,
};

This is similar to what we were doing in our previous APIs. Here we are simply getting data from the db, setting the variable todo, and then returning the response. If there is an error we simply return a standard error message in the catch block back to the user.

这类似于我们先前的API中所做的事情。 在这里,我们只是从db获取数据,将变量todo设置为,然后返回响应。 如果有错误,我们只需在catch块中将标准错误消息返回给用户即可。

Now fire up your terminal and make sure your MySQL instance is running. In your terminal type:

现在启动您的终端,并确保您MySQL实例正在运行。 在您的终端中输入:

$ deno run --allow-net server.ts

Go to Postman and run the API route for this controller.

转到Postman并为此控制器运行API路由。

Remember that every time we restart our server we reset the db. If you don't want this behavior, you can simply comment out the run function in the file db/client.ts.

请记住,每次重新启动服务器时,都会重置数据库。 如果您不希望出现这种情况,则只需在文件db/client.ts run函数。

So far we have done APIs for:

到目前为止,我们已经完成了以下API:

  • Get all todos获取所有待办事项
  • Create a new todo创建一个新的待办事项
  • Get a todo by ID通过ID获取待办事项

And here are the remaining APIs:

以下是其余的API:

  • Update a todo by ID通过ID更新待办事项
  • Delete a todo by ID通过ID删除待办事项

[PUT]通过ID API更新待办事项 ([PUT] update todo by id API)

Let's create a model for this API first. Go in our models/todo.ts file and add a definition for an updateById function:

首先让我们为此API创建一个模型。 进入我们的models/todo.ts文件,并为updateById函数添加定义:

*** Updates the content of a single todo item* @param id* @param todo* @param isCompleted* @returns integer (count of effect rows)*/
updateById: async ({ id, todo, isCompleted }: Todo) => {const result = await client.query(`UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,[todo,isCompleted,id,],);// return count of rows updatedreturn result.affectedRows;
},

The updateById takes in 3 params: id, todo, and isCompleted.

updateById接受3个参数: idtodoisCompleted

We simply run a MySQL query inside this function:

我们只需在此函数内运行一个MySQL查询:

onst result = await client.query(`UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,[todo,isCompleted,id,],
);

This updates a single todo item's todo and isCompleted by a specific id.

这将更新一个待办事项的todoisCompleted通过特定的id

Next we return a count of rows updated by this query by doing:

接下来,我们通过执行以下操作返回此查询更新的行数:

// return count of rows updatedreturn result.affectedRows;

The count will either be 0 or 1, but never more than 1. This is because we have unique IDs in our database – multiple todos with the same ID cannot exist.

计数将为0或1,但不得超过1。这是因为我们在数据库中具有唯一的ID –不能存在具有相同ID的多个待办事项。

Next go to our controllers/todo.ts file and add a definition for a updateTodoById function:

接下来转到我们的controllers/todo.ts文件,并为updateTodoById函数添加定义:

updateTodoById: async ({ params, request, response }: {params: { id: string };request: any;response: any;},
) => {try {const isAvailable = await TodoModel.doesExistById({ id: Number(params.id) },);if (!isAvailable) {response.status = 404;response.body = {success: false,message: "No todo found",};return;}// if todo found then update todoconst body = await request.body();const updatedRows = await TodoModel.updateById({id: Number(params.id),...body.value,});response.status = 200;response.body = {success: true,message: `Successfully updated ${updatedRows} row(s)`,};} catch (error) {response.status = 400;response.body = {success: false,message: `Error: ${error}`,};}
},

This is almost the same as of our previous APIs we wrote. The part that's new here is this:

这几乎与我们以前编写的API相同。 这是新的部分是:

// if todo found then update todo
const body = await request.body();
const updatedRows = await TodoModel.updateById({id: Number(params.id),...body.value,
});

We simple get the body that the user sends us in JSON and pass the body to our TodoModel.updateById function.

我们简单地获取用户以JSON发送给我们的主体,并将该主体传递给我们的TodoModel.updateById函数。

We have to convert the id to a number to comply with our Todo interface.

我们必须将id转换为数字以符合我们的Todo界面。

The query is executed and returns the count of updated rows. From there we simply return it in our response. If there is an error it goes to the catch block where we return our standard response message.

执行查询并返回更新的行数。 从那里,我们只是将其返回给我们。 如果有错误,它将转到catch块,在此我们返回标准响应消息。

Let's run this and see if it works. Make sure your MySQL instance is running and run the following from your terminal:

让我们运行它,看看它是否有效。 确保您MySQL实例正在运行,并在终端上运行以下命令:

$ deno run --allow-net server.ts

Go to Postman and run the API route for this controller:

转到Postman并为此控制器运行API路由:

[删除]通过ID API进行 ([DELETE] todo by id API)

In your models/todo.ts file create a function called deleteById:

在您的models/todo.ts文件中,创建一个名为deleteById的函数:

/*** Deletes a todo by ID* @param id* @returns integer (count of effect rows)*/
deleteById: async ({ id }: Todo) => {const result = await client.query(`DELETE FROM ${TABLE.TODO} WHERE id = ?`,[id],);// return count of rows updatedreturn result.affectedRows;
},

Here we simply pass an id as a param and then use the delete MySQL query. We then return the updated count of rows. The updated count will either be 0 or 1 because the ID of each todo is unique.

在这里,我们只是将id作为参数传递,然后使用delete MySQL查询。 然后,我们返回更新的行数。 由于每个待办事项的ID是唯一的,因此更新后的计数将为0或1。

Next, go in your controllers/todo.ts file and define a deleteByTodoId method:

接下来,进入您的controllers/todo.ts文件并定义一个deleteByTodoId方法:

/*** @description Delete todo by id* @route DELETE todos/:id*/
deleteTodoById: async ({ params, response }: { params: { id: string }; response: any },
) => {try {const updatedRows = await TodoModel.deleteById({id: Number(params.id),});response.status = 200;response.body = {success: true,message: `Successfully updated ${updatedRows} row(s)`,};} catch (error) {response.status = 400;response.body = {success: false,message: `Error: ${error}`,};}
},

This is pretty straightforward. We pass the params.id to our TodoModel.deleteById method and return the count of rows updated with this query.

这很简单。 我们将params.id传递给TodoModel.deleteById方法,并返回使用此查询更新的行数。

If anything goes wrong an error is thrown in the catch block which returns our standard error response.

如果发生任何错误,则在catch块中引发错误,该错误将返回我们的标准错误响应。

Let's check this out.

让我们检查一下。

Make sure your MySQL instance is running. In your terminal type:

确保您MySQL实例正在运行。 在您的终端中输入:

$ deno run --allow-net server.ts

Go to Postman and run the API route for this controller:

转到Postman并为此控制器运行API路由:

With this we are done with our Deno + Oak + MySQL tutorial.

至此,我们完成了Deno + Oak + MySQL教程。

The entire source code is available here: https://github.com/adeelibr/deno-playground. If you find an issue, just let me know. Or feel free to make a pull request and I'll give you credit in the repository.

完整的源代码可以在这里找到: https : //github.com/adeelibr/deno-playground 。 如果您发现问题,请告诉我。 或者随时提出拉取请求,我会在存储库中给您功劳。

If you found this tutorial helpful, please share it. And as always, I am available on Twitter under @adeelibr. I would love to hear your thoughts on it.

如果您认为本教程有帮助,请分享。 和往常一样,我可以在Twitter上的@adeelibr下访问 。 我很想听听您对此的想法。

翻译自: https://www.freecodecamp.org/news/how-to-use-mysql-in-deno-oak/

deno使用rust

deno使用rust_如何在Deno和Oak中使用MySQL相关推荐

  1. 如何在VS和CB中配置MySQL环境

    这里,由于我的MySQL安装在D盘 MY SQL\MySQL Server 5.6该路径下,所以后面的路径均以D:\MY SQL\MySQL Server 5.6开头 在VS中配置MySQL环境 包含 ...

  2. 如何在 Deno 中构建一个 URL 短链生成器

    作者 | 韩亦乐       责编 | 欧阳姝黎 原文地址:How to Build a URL Shortener in Deno 原文作者:Akash Joshi 译者:hylerrix 备注:本 ...

  3. deno mysql_从 Node 到 Deno

    我收集了一些 Node 中最常用的主题,并寻找 Deno 的替代方案.首先我想说明,许多当前的 Node.js 模块都可以都可以用在 Deno 中.由于许多模块都是可重用的,所以没有必要为所有方法去寻 ...

  4. 2022年是否有必要用Deno代替Node选择以及Deno的资源大全

    2022年是否有必要用Deno代替Node选择以及Deno的资源大全 我的答案是:没有.以下内容纯属心得和体验,无技术点,记录今天了解的deno和它目前生态等发展 deno官网:https://den ...

  5. linux mint 修改dns,如何在Ubuntu和LinuxMint中刷新DNS缓存

    本篇文章给大家介绍的内容是关于如何在Ubuntu和LinuxMint中刷新DNS缓存,下面我们来看具体的内容. 域名系统(DNS)是互联网的主干网之一.你无法想象在全球数百万用户的公共网络上运行网站. ...

  6. 聊天软交互原理_来自不同城市的人们如何在freeCodeCamp聊天室中进行交互

    聊天软交互原理 by Déborah Mesquita 由DéborahMesquita 来自不同城市的人们如何在freeCodeCamp聊天室中进行交互 (How people from diffe ...

  7. graphql redux_如何在Redux应用程序中使用GraphQL

    graphql redux by Howon Song 通过宋颂恩 如何在Redux应用程序中使用GraphQL (How to use GraphQL in your Redux app) Fetc ...

  8. 【面试现场】如何在10亿数中找出前1000大的数

    小史是一个应届生,虽然学的是电子专业,但是自己业余时间看了很多互联网与编程方面的书,一心想进BAT互联网公司. 之前小史在BAT三家的面试中已经挂了两家,今天小史去了BAT中的最后一家面试了. 简单的 ...

  9. 如何在 Mutt 邮件客户端中使用密文密码

    如何在 Mutt 邮件客户端中使用密文密码 Mutt 是一个 Linux/UNIX 终端环境下的开源的邮件客户端.Mutt 以及 Alpine 在 Linux 命令行爱好者中有着最忠诚的追随者,这不是 ...

最新文章

  1. CSS入门-五个简单,但有用的CSS属性
  2. 用Java实现天天酷跑(附源码),这个真的有点强了!
  3. 万网稳居国内域名主机网站榜首 西部数码第二
  4. 数制系统之间的转换总结(各进制的转换)
  5. 【NLP】发现一篇专门吐槽 NLP 内卷现状的 ACL 论文 ...
  6. Dev GridView 绑定Listlt;Tgt;、BindingList lt;Tgt;、BindingSource
  7. LNMP Nginx 499 问题 第三方回调异常
  8. PyFlink 在聚美优品的应用实践
  9. java 安卓权限_java – Android运行时权限 – 如何实现
  10. c程序语言符号的作用,c语言宏定义中的#,##,#@及\符号的作用
  11. Java基础(四) StringBuffer、StringBuilder原理浅析
  12. lambda表达式和切片
  13. AMOS结构方程模型(SEM)简介【SPSS 049期】
  14. EXCEL电子档色环电阻计算器
  15. css vss irf,网络虚拟化技术:VSS、IRF2和CSS解析
  16. ctc center-loss在字符识别形近字分类中的使用
  17. 计算机考研是属于工学呢还是理学呀,计算机考研是属于工学呢还是理学
  18. Qt中正确设置子窗口关闭方式
  19. 基于JSP的智能道路交通信息管理系统
  20. Google天气接口

热门文章

  1. ie8加载js太慢_js ie8 慢
  2. Angular Http
  3. 大转盘完整源码附效果图,可以下载直接用
  4. 【Python】在Mac系统中安装Pygame
  5. Java并发面试,幸亏有点道行,不然又被忽悠了
  6. 中国大学MOOC-C程序设计(浙大翁恺)—— 时间换算
  7. MySQL练习题:常用函数
  8. Enterprise Library 4 缓存应用程序块的设计
  9. Android -- Annotation(注解)原理详解及常见框架应用
  10. 提升Hadoop计算能力的并行框架