Gần đây tôi đã viết về cách tạo API Todo trong Deno + Oak (mà không sử dụng cơ sở dữ liệu) . Bạn có thể tìm thấy repo trong chương_1:sồi trên GitHub.
Hướng dẫn này tiếp tục phần còn lại và tôi sẽ xem xét cách tích hợp MySQL vào một dự án Deno và Oak.
Nếu bất kỳ lúc nào bạn muốn xem toàn bộ mã nguồn được sử dụng trong hướng dẫn này, nó có sẵn tại chương_2:mysql . Vui lòng cho nó một ngôi sao trên GitHub nếu bạn thích nó.
Tôi giả định rằng bạn đã hoàn thành hướng dẫn cuối cùng được đề cập ở trên. Nếu không, hãy xem tại đây và quay lại khi bạn hoàn thành.
Trước khi chúng tôi bắt đầu, hãy đảm bảo rằng bạn đã cài đặt và chạy ứng dụng khách MySQL:
- Máy chủ cộng đồng MySQL [Tải xuống tại đây]
- MySQL Workbench [Tải xuống tại đây]
Tôi đã viết một hướng dẫn nhỏ cho người dùng Mac OS về cách thiết lập MySQL vì tôi cũng phải vật lộn với nó. Kiểm tra nó tại đây.
Nếu bạn đang sử dụng máy tính Windows, bạn có thể sử dụng các công cụ tương tự hoặc bạn cũng có thể sử dụng XAMPP để chạy phiên bản MySQL trong bảng điều khiển của bạn.
Khi bạn có phiên bản MySQL đang chạy, chúng tôi có thể bắt đầu hướng dẫn của mình.
Hãy bắt đầu
Giả sử rằng bạn đến từ bài viết này, API Todo trong Deno + Oak (không sử dụng cơ sở dữ liệu) , chúng tôi sẽ làm như sau:
- Tạo kết nối cơ sở dữ liệu MySQL
- Viết một tập lệnh nhỏ để đặt lại cơ sở dữ liệu mỗi khi chúng tôi khởi động máy chủ Deno của mình
- Thực hiện các thao tác CRUD trên bảng
- Thêm chức năng CRUD vào bộ điều khiển API của chúng tôi
Một điều cuối cùng - đây là toàn bộ sự khác biệt cam kết đã được thực hiện trong Chương 1 để thêm MySQL vào dự án (mã nguồn hiển thị các bổ sung mới được thực hiện từ chương 1).
Trong thư mục gốc dự án của bạn - của tôi có tên là chapter_2:mysql
, mặc dù của bạn có thể được gọi là bất cứ thứ gì bạn muốn - tạo một thư mục có tên db . Bên trong thư mục đó, tạo một tệp có tên config.ts và thêm nội dung sau vào nó:
export const DATABASE: string = "deno";
export const TABLE = {
TODO: "todo",
};
Không có gì lạ ở đây, chỉ cần xác định tên cơ sở dữ liệu của chúng ta cùng với một đối tượng cho các bảng và sau đó xuất nó. Dự án của chúng tôi sẽ có một cơ sở dữ liệu được gọi là "cons" và bên trong db đó, chúng tôi sẽ chỉ có một bảng được gọi là "todo".
Tiếp theo, bên trong db , hãy tạo một tệp khác có tên client.ts và thêm nội dung sau:
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;
Một vài điều đang xảy ra ở đây.
Chúng tôi đang nhập Client
từ mysql
thư viện. Client
sẽ giúp chúng tôi kết nối với cơ sở dữ liệu của mình và thực hiện các hoạt động trong cơ sở dữ liệu.
client.connect({
hostname: "127.0.0.1",
username: "root",
password: "",
db: "",
});
Client
cung cấp một phương thức có tên là connect
lấy đối tượng mà chúng tôi có thể cung cấp hostname
, username
, password
và db
. Với thông tin này, nó có thể thiết lập kết nối với phiên bản MySQL của chúng tôi.
Đảm bảo rằng username
của bạn không có password
, vì nó sẽ xung đột với việc kết nối với thư viện MySQL của Deno. Nếu bạn không biết cách làm điều đó, hãy đọc hướng dẫn tôi đã viết này.
Tôi đã rời khỏi database
trường trống ở đây vì tôi muốn chọn nó theo cách thủ công sau này trong tập lệnh của mình.
Hãy thêm một tập lệnh sẽ khởi tạo một cơ sở dữ liệu có tên là "de", chọn nó và bên trong db đó, hãy tạo một bảng có tên là "todo".
Bên trong db/client.ts
tệp, hãy thực hiện một số bổ sung mới:
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 db
await client.execute(`USE ${DATABASE}`);
// delete table if it exists before
await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
// create table
await 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;
Ở đây chúng tôi đang nhập DATABASE
và TABLE
từ tệp cấu hình của chúng tôi, sau đó sử dụng các giá trị đó trong một hàm mới có tên là run()
.
Hãy chia nhỏ run()
này hàm số. Tôi đã thêm nhận xét vào tệp để giúp bạn hiểu quy trình làm việc:
const run = async () => {
// create database (if not created before)
await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
// select db
await client.execute(`USE ${DATABASE}`);
// delete table if it exists before
await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
// create table
await 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();
- Tạo cơ sở dữ liệu có tên
deno
. Nếu nó đã tồn tại thì không cần làm gì cả. - Sau đó, chọn cơ sở dữ liệu để sử dụng, cơ sở dữ liệu này được gọi là
deno
- Xóa bảng bên trong
deno
được gọi làtodo
nếu nó đã tồn tại. - Tiếp theo, tạo một bảng mới bên trong
deno
db, gọi nó làtodo
và xác định cấu trúc của nó:Nó sẽ có một gia số tự động duy nhấtid
sẽ là một số nguyên, một trường khác được gọi làtodo
sẽ là một chuỗi và cuối cùng là một trường có tênisCompleted
đó là một boolean. Tôi cũng xác địnhid
làm khóa chính của tôi.
Lý do tôi viết script này là vì tôi không muốn có thêm thông tin trong MySQL instance. Mỗi khi tập lệnh chạy, nó chỉ khởi động lại mọi thứ.
Bạn không cần phải thêm tập lệnh này. Nhưng nếu không, bạn sẽ phải tạo db và bảng theo cách thủ công.
Ngoài ra, hãy xem tài liệu của thư viện Deno MySQL về tạo db và tạo bảng.
Quay trở lại chương trình làm việc của chúng tôi, chúng tôi vừa đạt được hai điều trong số bốn điều được đề cập ở đầu bài viết:
- Tạo kết nối cơ sở dữ liệu MySQL
- Viết một tập lệnh nhỏ để đặt lại cơ sở dữ liệu mỗi khi chúng tôi khởi động máy chủ Deno của mình
Đó đã là 50% của hướng dẫn. Thật không may, chúng tôi không thể thấy nhiều điều xảy ra ngay bây giờ. Hãy nhanh chóng thêm một số chức năng để xem nó hoạt động.
Thực hiện các hoạt động CRUD trên bảng và thêm chức năng vào bộ điều khiển API của chúng tôi
Trước tiên, chúng ta cần cập nhật giao diện Todo của mình. Truy cập interfaces/Todo.ts
tệp và thêm những thứ sau:
export default interface Todo {
id?: number,
todo?: string,
isCompleted?: boolean,
}
Cái gì đây ?
nó làm cho khóa trong đối tượng là tùy chọn. Tôi đã làm điều này vì sau này tôi sẽ sử dụng các hàm khác nhau để chuyển các đối tượng chỉ có id
, todo
, isCompleted
hoặc tất cả chúng cùng một lúc.
Nếu bạn muốn tìm hiểu thêm về các thuộc tính tùy chọn trong TypeScript, hãy truy cập tài liệu của chúng tại đây.
Tiếp theo, tạo một thư mục mới có tên là mô hình và bên trong thư mục đó, hãy tạo một tệp có tên todo.ts . Thêm nội dung sau vào tệp:
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) => {},
};
Ngay bây giờ các chức năng đang trống, nhưng điều đó không sao. Chúng tôi sẽ điền từng cái một.
Tiếp theo, truy cập controllers/todo.ts
và đảm bảo rằng bạn thêm những thứ sau:
// 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 },
) => {},
};
Ở đây chúng tôi cũng có các chức năng trống. Hãy bắt đầu lấp đầy chúng.
[Nhận] tất cả API của todos
Bên trong models/todo.ts
, thêm định nghĩa cho một hàm có tên là getAll
:
import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";
export default {
/**
* Will return all the entries in the todo column
* @returns array of todos
*/
getAll: async () => {
return await client.query(`SELECT * FROM ${TABLE.TODO}`);
},
}
Client
cũng cho thấy một phương pháp khác ngoài connect
(chúng tôi đã sử dụng phương thức "kết nối" trong db/client.ts
tệp) và đó là query
. client.query
phương thức cho phép chúng tôi chạy các truy vấn MySQL trực tiếp từ mã Deno của chúng tôi.
Tiếp theo, truy cập controllers/todo.ts
thêm định nghĩa cho getAllTodos
:
// 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}`,
};
}
},
}
Tất cả những gì chúng tôi đang làm là nhập TodoModel
và sử dụng phương thức của nó được gọi là getAll
, mà chúng tôi vừa xác định bây giờ. Vì nó trả về như một lời hứa nên chúng tôi đã gói nó trong async / await.
Phương thức TodoModel.getAll()
sẽ trả về cho chúng ta một mảng mà chúng ta chỉ cần trả về response.body
với trạng thái status
đặt thành 200
.
Nếu lời hứa không thành công hoặc có lỗi khác, chúng tôi chỉ cần đi đến khối bắt của chúng tôi và trả về trạng thái 400 với success
đặt thành false. Chúng tôi cũng đặt message
những gì chúng tôi nhận được từ khối bắt.
Vậy là xong. Bây giờ hãy khởi động thiết bị đầu cuối của chúng ta.
Đảm bảo rằng phiên bản MySQL của bạn đang chạy. Trong loại thiết bị đầu cuối của bạn:
$ deno run --allow-net server.ts
Thiết bị đầu cuối của bạn sẽ trông giống như sau:
Bảng điều khiển của tôi đang cho tôi biết hai điều ở đây.
- Máy chủ Deno API của tôi đang chạy trên cổng 8080
- Phiên bản MySQL của tôi đang chạy trên
127.0.0.1
, làlocalhost
Hãy kiểm tra API của chúng tôi. Tôi đang sử dụng Postman ở đây, nhưng bạn có thể sử dụng ứng dụng khách API yêu thích của mình.
Ngay bây giờ nó chỉ trả về dữ liệu trống. Nhưng khi chúng tôi thêm dữ liệu vào todo
của mình bảng, nó sẽ trả về những việc cần làm ở đây.
Tuyệt vời. Còn một API nữa và còn bốn API nữa.
[Đăng] thêm một API todo
Trong models/todo.ts
tệp, thêm định nghĩa sau cho add()
chức năng:
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,
],
);
},
}
Hàm add nhận đối tượng làm đối số, có hai mục:todo
và isCompleted
.
Vì vậy, add: async ({ todo, isCompleted }: Todo) => {}
cũng có thể được viết là ({todo, isCompleted}: {todo:string, isCompleted:boolean})
. Nhưng vì chúng ta đã có một giao diện được xác định trong interfaces/Todo.ts
của chúng ta tệp đó là
export default interface Todo {
id?: number,
todo?: string,
isCompleted?: boolean,
}
chúng ta chỉ có thể viết cái này là add: async ({ todo, isCompleted }: Todo) => {}
. Điều này cho TypeScript biết rằng hàm này có hai đối số, todo
, là một chuỗi và isCompleted
, là một boolean.
Nếu bạn muốn đọc thêm về các giao diện, TypeScript có một tài liệu tuyệt vời về nó mà bạn có thể tìm thấy tại đây.
Bên trong chức năng của chúng tôi, chúng tôi có những thứ sau:
return await client.query(
`INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)`,
[
todo,
isCompleted,
],
);
Truy vấn này có thể được chia thành hai phần:
-
INSERT INTO ${TABLE.TODO}(todo, isCompleted) values(?, ?)
. Hai dấu chấm hỏi ở đây biểu thị việc sử dụng các biến bên trong truy vấn này. - Phần khác,
[todo, isCompleted]
, là các biến sẽ xuất hiện trong phần đầu tiên của truy vấn và được thay thế bằng(?, ?)
-
Table.Todo
chỉ là một chuỗi đến từ tệpdb/config.ts
nơiTable.Todo
giá trị là "todo
"
Tiếp theo bên trong controllers/todo.ts
của chúng tôi , hãy chuyển đến định nghĩa của createTodo()
chức năng:
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}`,
};
}
},
}
Hãy chia điều này thành hai phần:
Phần 1
const body = await request.body();
if (!request.hasBody) {
response.status = 400;
response.body = {
success: false,
message: "No data provided",
};
return;
}
Tất cả những gì chúng tôi đang làm ở đây là kiểm tra xem người dùng có đang gửi dữ liệu trong cơ thể hay không. Nếu không, thì chúng tôi trả về trạng thái 400
và trong phần nội dung trả về success: false
và message: <erromessage-string>
.
Phần 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}`,
};
}
Nếu không có lỗi, TodoModel.add()
hàm được gọi và chỉ trả về trạng thái 200
và một thông báo xác nhận cho người dùng.
Nếu không, nó chỉ tạo ra một lỗi tương tự mà chúng tôi đã làm trong API trước đó.
Bây giờ chúng ta đã hoàn thành. Kích hoạt thiết bị đầu cuối của bạn và đảm bảo phiên bản MySQL của bạn đang chạy. Trong loại thiết bị đầu cuối của bạn:
$ deno run --allow-net server.ts
Đi tới Người đưa thư và chạy tuyến API cho bộ điều khiển này:
Điều này thật tuyệt, bây giờ chúng ta có hai API đang hoạt động. Chỉ còn ba lần nữa.
[GET] todo by id API
Trong models/todo.ts
của bạn , thêm định nghĩa cho hai hàm này, doesExistById()
và 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],
);
},
}
Hãy nói về từng chức năng một:
-
doesExistById
lấy mộtid
và trả vềboolean
cho biết một việc cụ thể có tồn tại trong cơ sở dữ liệu hay không.
Hãy chia nhỏ chức năng này:
const [result] = await client.query(
`SELECT COUNT(*) count FROM ${TABLE.TODO} WHERE id = ? LIMIT 1`,
[id],
);
return result.count > 0;
Chúng tôi chỉ cần kiểm tra số lượng ở đây trong bảng với một id việc làm cụ thể. Nếu số lượng lớn hơn 0, chúng tôi trả về true
. Nếu không, chúng tôi trả về false
.
-
getById
trả về mục việc cần làm so với một id cụ thể:
return await client.query(
`SELECT * FROM ${TABLE.TODO} WHERE id = ?`,
[id],
);
Chúng tôi chỉ đơn giản là chạy một truy vấn MySQL ở đây để lấy một việc cần làm theo id và trả về kết quả như hiện tại.
Tiếp theo, đi tới controllers/todo.ts
của bạn và thêm định nghĩa cho getTodoById
phương pháp bộ điều khiển:
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}`,
};
}
},
}
Hãy chia điều này thành hai phần nhỏ hơn:
const isAvailable = await TodoModel.doesExistById(
{ id: Number(params.id) },
);
if (!isAvailable) {
response.status = 404;
response.body = {
success: false,
message: "No todo found",
};
return;
}
Trước tiên, chúng tôi kiểm tra xem việc cần làm có tồn tại trong cơ sở dữ liệu so với một id hay không bằng cách sử dụng phương pháp này:
const isAvailable = await TodoModel.doesExistById(
{ id: Number(params.id) },
);
Ở đây chúng ta cần chuyển đổi params.id
thành một Number
bởi vì giao diện việc làm của chúng tôi chỉ chấp nhận id
như một con số. Tiếp theo, chúng ta chỉ cần chuyển params.id
vào doesExistById
phương pháp. Phương thức này sẽ trả về dưới dạng boolean.
Sau đó, chúng tôi chỉ cần kiểm tra xem việc cần làm không có sẵn và trả về 404
với phản hồi tiêu chuẩn của chúng tôi như với các điểm cuối trước đó:
if (!isAvailable) {
response.status = 404;
response.body = {
success: false,
message: "No todo found",
};
return;
}
Sau đó, chúng tôi có:
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}`,
};
Điều này tương tự như những gì chúng tôi đã làm trong các API trước đây của mình. Ở đây, chúng tôi chỉ lấy dữ liệu từ db, đặt biến todo
, và sau đó trả lại phản hồi. Nếu có lỗi, chúng tôi chỉ cần trả lại thông báo lỗi chuẩn trong khối bắt lại cho người dùng.
Bây giờ kích hoạt thiết bị đầu cuối của bạn và đảm bảo rằng phiên bản MySQL của bạn đang chạy. Trong loại thiết bị đầu cuối của bạn:
$ deno run --allow-net server.ts
Truy cập Postman và chạy API route cho bộ điều khiển này.
Hãy nhớ rằng mỗi khi chúng tôi khởi động lại máy chủ của mình, chúng tôi đặt lại db. Nếu bạn không muốn hành vi này, bạn có thể chỉ cần nhận xét về run
chức năng trong tệp db/client.ts
.
Cho đến nay, chúng tôi đã thực hiện các API cho:
- Nhận tất cả các việc cần làm
- Tạo một việc làm mới
- Nhận việc làm theo ID
Và đây là các API còn lại:
- Cập nhật một việc làm theo ID
- Xóa một việc cần làm theo ID
[PUT] cập nhật việc cần làm bằng id API
Trước tiên, hãy tạo một mô hình cho API này. Truy cập models/todo.ts
của chúng tôi và thêm định nghĩa cho một updateById
chức năng:
**
* 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 updated
return result.affectedRows;
},
updateById
có 3 tham số:id
, todo
và isCompleted
.
Chúng tôi chỉ chạy một truy vấn MySQL bên trong hàm này:
onst result = await client.query(
`UPDATE ${TABLE.TODO} SET todo=?, isCompleted=? WHERE id=?`,
[
todo,
isCompleted,
id,
],
);
Điều này cập nhật todo
của một mục duy nhất và isCompleted
bởi một id
cụ thể .
Tiếp theo, chúng tôi trả về số lượng hàng được cập nhật bởi truy vấn này bằng cách thực hiện:
// return count of rows updated
return result.affectedRows;
Số lượng sẽ là 0 hoặc 1, nhưng không bao giờ nhiều hơn 1. Điều này là do chúng tôi có các ID duy nhất trong cơ sở dữ liệu của mình - không thể tồn tại nhiều việc cần làm với cùng một ID.
Tiếp theo, hãy truy cập controllers/todo.ts
của chúng tôi và thêm định nghĩa cho updateTodoById
chức năng:
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 todo
const 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}`,
};
}
},
Điều này gần giống với các API trước đây của chúng tôi mà chúng tôi đã viết. Phần mới ở đây là cái này:
// if todo found then update todo
const body = await request.body();
const updatedRows = await TodoModel.updateById({
id: Number(params.id),
...body.value,
});
Chúng tôi đơn giản lấy phần thân mà người dùng gửi cho chúng tôi trong JSON và chuyển phần nội dung đó vào TodoModel.updateById
của chúng tôi chức năng.
Chúng ta phải chuyển đổi id
tới một số để tuân thủ giao diện Todo của chúng tôi.
Truy vấn được thực thi và trả về số lượng hàng được cập nhật. Từ đó, chúng tôi chỉ cần trả lại nó trong phản hồi của chúng tôi. Nếu có lỗi, nó sẽ chuyển đến khối bắt nơi chúng tôi trả về thông báo phản hồi tiêu chuẩn của mình.
Hãy chạy cái này và xem nó có hoạt động không. Đảm bảo phiên bản MySQL của bạn đang chạy và chạy phần sau từ thiết bị đầu cuối của bạn:
$ deno run --allow-net server.ts
Đi tới Người đưa thư và chạy tuyến API cho bộ điều khiển này:
[DELETE] todo by id API
Trong models/todo.ts
của bạn tệp tạo một chức năng có tên là 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 updated
return result.affectedRows;
},
Ở đây, chúng tôi chỉ cần chuyển một id
dưới dạng tham số và sau đó sử dụng truy vấn MySQL xóa. Sau đó, chúng tôi trả về số lượng hàng đã cập nhật. Số lượng cập nhật sẽ là 0 hoặc 1 vì ID của mỗi việc làm là duy nhất.
Tiếp theo, truy cập controllers/todo.ts
của bạn và xác định một deleteByTodoId
phương pháp:
/**
* @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}`,
};
}
},
Việc này thật thẳng thắn. Chúng tôi chuyển params.id
tới TodoModel.deleteById
của chúng tôi và trả về tổng số hàng được cập nhật với truy vấn này.
Nếu có bất cứ điều gì sai, một lỗi sẽ được đưa vào khối bắt trả về phản hồi lỗi chuẩn của chúng tôi.
Hãy kiểm tra điều này.
Đảm bảo rằng phiên bản MySQL của bạn đang chạy. Trong loại thiết bị đầu cuối của bạn:
$ deno run --allow-net server.ts
Đi tới Người đưa thư và chạy tuyến API cho bộ điều khiển này:
Với điều này, chúng ta đã hoàn thành với hướng dẫn Deno + Oak + MySQL.
Toàn bộ mã nguồn có sẵn tại đây:https://github.com/adeelibr/deno-playground. Nếu bạn tìm thấy một vấn đề, chỉ cần cho tôi biết. Hoặc vui lòng đưa ra yêu cầu kéo và tôi sẽ cấp cho bạn tín dụng trong kho lưu trữ.
Nếu bạn thấy hướng dẫn này hữu ích, hãy chia sẻ nó. Và như mọi khi, tôi có mặt trên Twitter dưới tên @adeelibr. Tôi rất muốn nghe suy nghĩ của bạn về điều đó.