iT邦幫忙

第 12 屆 iThome 鐵人賽

0
自我挑戰組

玩轉 React 從0到1系列 第 29

【Day 29】Deno + Oak 建立 Restful API (2)

https://ithelp.ithome.com.tw/upload/images/20201014/20109963EeoAMWDT8V.jpg

接續昨天繼續實作

還記得我們昨天在 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";

顯示 Todo

getAllTodos: ({ response }: { response: any }) => {
    response.status = 200;
    response.body = {
      success: true,
      data: todos,  // 搜尋全部,自動帶入我們的假資料
    };
  }

這裏的 getAllTodos 其實是 getAllTodos: (context) => {},而這裏 context 可以有三個變數:

  • request: 使用者發送過來的資料,像是請求或是夾帶參數
  • response: 瀏覽器返回經過 API 後回覆的資料
  • params: 像我們要查詢某個 id 的資料,就是從這裡帶進來的

response.status 代表的是這個API的回覆狀態,可能是200(代表成功),也可能是 404(找不到)
response.body 則是 API 的主要回覆資料

顯示單筆 Todo

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

新增 Todo

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 的資料陣列中並回傳。

修改 Todo

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相同就覆蓋過去,最後送出更新後的資料。

刪除 Todo

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

結論

  • 介紹完整的 oak Restful API

/images/emoticon/emoticon06.gif


上一篇
【Day 28】Deno + Oak 建立 Restful API (1)
下一篇
【Day 30】鐵人賽後心得
系列文
玩轉 React 從0到130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言