還記得我們昨天在 Controller 裡新增的 todo.ts ?
export default {
getAllTodos: () => {}, // 顯示 Todo
createTodo: async () => {}, // 新增 Todo
getTodoById: () => {}, // 顯示單筆 Todo
updateTodoById: async () => {}, // 修改 Todo
deleteTodoById: () => {}, // 刪除 Todo
}
接下來我們要分別實作這些方法了~~
// v4 是用於產生 string 型別的 id
import { v4 } from "https://deno.land/std/uuid/mod.ts";
// 引入 Todo 這個介面,約束傳遞進來的資料
import Todo from "../interfaces/Todo.ts";
// 引入我們 Mock 的假資料
import todos from "../stubs/todos.ts";
getAllTodos: ({ response }: { response: any }) => {
response.status = 200;
response.body = {
success: true,
data: todos, // 搜尋全部,自動帶入我們的假資料
};
}
這裏的 getAllTodos 其實是 getAllTodos: (context) => {},而這裏 context 可以有三個變數:
response.status 代表的是這個API的回覆狀態,可能是200(代表成功),也可能是 404(找不到)
response.body 則是 API 的主要回覆資料
getTodoById: (
{ params, response }: { params: { id: string }; response: any },
) => {
const todo: Todo | undefined = todos.find((t) => {
return t.id === params.id;
});
if (!todo) {
response.status = 404;
response.body ={
success: false,
message: 'No Todo Found',
};
return;
}
response.status = 200;
response.body = {
success: true,
data: todo,
};
}
這裏的 { params: { id: string }
代表帶入 id 作為參數去做尋找
const todo 這段是在說將 todo 變數設置為 Todo 類型或是 undefined,它不能是其他類型!!然後用 id 去比對所有的物件,一般取得單筆會去確認此筆單是否存在,存在返回資料與 200 status,不存在返回 404 與 No Todo Found
。
createTodo: async (
{ request, response }: { request: any; response: any },
) => {
const body = await request.body(); // 這裏返回的是 promise<pending>
if (!request.hasBody) {
response.status = 400;
response.body = { message: "No data provided" };
return;
}
const result = await body.value; // 這裏返回的是 string
const item = JSON.parse(result);
const newTodo: Todo = {
id: v4.generate(),
todo: item.todo,
isCompleted: false,
};
let data = [...todos, newTodo];
response.body = {
success: true,
data,
};
}
首先在 const body
的部分去讀取使用者傳遞過來的資料,接下來用 oak 內建的 request.hasBody
去判斷是否傳遞過來的值是空的,空的就返回 status:400 跟訊息。const result
則是去取得 body 內部 value 的值在去 JSON.parse 成物件,這裡要注意,否則會出錯,變成空值
,最後寫成 Todo 類型的形式存入我們原先 mock 的資料陣列中並回傳。
updateTodoById: async (
{ params, request, response }: {
params: { id: string },
request: any,
response: any,
}
) => {
const todo: Todo | undefined = todos.find((t) => t.id === params.id);
if (!todo) {
response.status = 404;
response.body = {
success: false,
message: "No todo found",
};
return;
}
const body = await request.body();
const result = await body.value;
const updatedData: { todo?: string; isCompleted?: boolean } = JSON.parse(result);
let newTodos = todos.map((t) => {
return t.id === params.id ? { ...t, ...updatedData } : t;
});
response.status = 200;
response.body = {
success: true,
data: newTodos,
};
}
這裏帶入 id 來尋找此筆資料更新,跟取得單筆一樣,都是先去判斷是否存在,因為如果不存在是無法更新的。{ todo?: string; isCompleted?: boolean }
,這裏將型別的檢查添加到 updatedData 上,以及代表的是有可能包含或不包含 todo 跟 isCompleted, 最後將 JSON.parse(result) 賦值給 updatedData,
而 let newTodos 這段則是檢查全部當 id 與使用者送進來的 id相同就覆蓋過去,最後送出更新後的資料。
deleteTodoById: (
{ params, response }: { params: { id: string }; response: any },
) => {
const todo: Todo | undefined = todos.find((t) => {
return t.id === params.id;
});
if (!todo) {
response.status = 404;
response.body ={
success: false,
message: 'No Todo Found',
};
return;
}
const allTodos = todos.filter((t) => t.id !== params.id);
response.status = 200;
response.body = {
success: true,
data: allTodos,
}
}
這裏帶入 id 來尋找此筆資料刪除,跟取得單筆一樣,都是先去判斷是否存在,因為如果不存在是無法刪除的。
比較特別的是,這邊是用 filter 去處理,刪除掉 todo.id 與 params.id 一樣的物件。
Create a Simple REST API with Deno