iT邦幫忙

2023 iThome 鐵人賽

DAY 6
1

https://ithelp.ithome.com.tw/upload/images/20230920/20136558P7twYLUeeL.png
圖片來源:MDN

大綱

  1. MVC架構簡介
  2. Controller介紹和建立
  3. ErrorModel

1. MVC架構簡介

MVC是指(Model-View-Controller),是一種軟體架構模式,把軟體系統分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller),將應用程式的不同部分分離開來。
這樣使後續對程式的修改和擴充簡化,並且能讓程式某一部分重複利用。
除此之外,此模式透過對複雜度的簡化,也讓程式結構更加直覺。

  • Model(模型):

模型代表了應用程式的資料層。它負責處理資料的讀取、寫入、驗證和操作。
在Express.js中,通常使用ORM(物件關係對映)庫(例如Mongoose)來定義模型,並與資料庫進行互動。

  • View(視圖):
    視圖是使用者界面的部分,負責將資料呈現給使用者。視圖通常是模板文件,包含HTML和動態內容(例如資料變數)的結合。(這次不會實作到)

  • Controller(控制器):
    控制器是應用程式的業務邏輯和控制流的中心。它處理HTTP請求,協調模型和視圖的互動,並將結果回傳給客戶端。

想了解更多請參考What is the MVC, Creating a [Node.js-Express] MVC Application

2. Controller

在開始前先來回顧,這是目前的posts-routes.js

const express = require('express');
const router = express.Router();

const MOCK_POSTS = [
    {
        id: 'p1',
        title: '文章1',
        content:'ChatGPT'
    },
    {
        id: 'p2',
        title: '文章2',
        content:'Micro frontend'
    }
]

//@router POST /api/posts
//@desc 新增文章.
//@access Public
router.post("/", (req,res,next)=>{
    res.json({message: 'It works!'});
});

//@router  GET api/posts/:postId
//@desc 取得文章資訊(單一).
//@access Public
router.get("/:postId",(req,res,next)=>{
    const postId = req.params.postId;
    const post = MOCK_POSTS.find(post =>{
        return post.id === postId;
    });

    //若文章不存在於假資料(資料庫)
    if(!post){
        const error = new Error('此id的文章不存在');
        error.status = 404;
        throw error; //會觸發error middleware
    }
    res.json({post});
});

//@router PUT /api/posts/:postId
//@desc 編輯文章
//@access Public
router.put("/:postId", (req,res,next)=>{
    res.json({message: 'It works!'});
});

//@router DELETE api/posts
//@desc 刪除文章
//@access Public*/
router.delete("/:postId", (req,res,next)=>{
    res.json({message: 'It works!'});
});


module.exports =  router;

其實可以看到我們目前只加了一個取文章資料的邏輯,整個檔案內容就明顯變多了,這時候就很適合使用Controller來管理檔案。

Controller介紹

Controller負責定義和處理路由。當使用者訪問特定的URL時,Express的路由器將根據路由設置將請求導向相應的Controller函數,這樣Controller就可以處理該請求。

還記得上一篇在介紹的routes時,有列出他的結構

app.METHOD(PATH, HANDLER)

其中HANDLER是當路由相符時要執行的函數,就是要擺放controller的地方

首先我們先在資料夾底下建立一個controllers資料夾,接著建立posts-controller.js
https://ithelp.ithome.com.tw/upload/images/20230921/20136558103EnBKY95.jpg

我們把posts-routes.js裡取得文章資料api的Handler還有假資料移到posts-controller.js裡。

//posts-controller.js 

const MOCK_POSTS = [
    {
        id: 'p1',
        title: '文章1',
        content:'ChatGPT'
    },
    {
        id: 'p2',
        title: '文章2',
        content:'Micro frontend'
    }
]

//取得文章資料
const getPost =  (req,res,next)=>{
    const postId = req.params.postId;
    const post = MOCK_POSTS.find(post =>{
        return post.id === postId;
    });

    //若文章不存在於假資料(資料庫)
    if(!post){
        const error = new Error('此id的文章不存在');
        error.status = 404;
        throw error; //會觸發error middleware
    }
    res.json({post});
}

//將controller export出去
exports.getPost = getPost;

接著回到posts-routes.js,來引入剛剛設置好的controller


const express = require("express");
const router = express.Router();
//引入posts-controller
const postControllers = require("../../controllers/posts-controller");

//@router  GET api/posts/:postId
//@desc Get single post.
//@access Public
router.get("/:postId", postControllers.getPost);

...(略)

這樣我們的posts-routes.js就變得乾淨很多了!

3. Error Model

目前程式碼其實已經很簡潔了,但還有個部分可以抽出來進行處理,那就是錯誤訊息

在專案資料夾底下建立models資料夾,並在裡面建立http-error.js
https://ithelp.ithome.com.tw/upload/images/20230921/20136558NJ8rsJoRvC.jpg

//http-error.js

class HttpError extends Error {
    constructor(message, errorCode){
        super(message);
        this.code = errorCode;
    }
}

module.exports = HttpError;

回到我們的posts-controller.js去引入我們的modelHttpError

const HttpError = require('../models/http-error');

const getPost =  (req,res,next) =>{
    const postId = req.params.postId;
    const post = MOCK_POSTS.find(post =>{
        return post.id === postId;
    });

    //若文章不存在於假資料(資料庫)
    if(!post){
         //使用error-model
        throw  new HttpError('此id的文章不存在',404);
    }
    res.json({post});
} 

參考資料

https://zh.wikipedia.org/zh-tw/MVC
https://www.geeksforgeeks.org/how-to-use-get-parameter-in-express-js/


上一篇
[Day5] 文章資料API規劃和Express的錯誤處理
下一篇
[Day7] 文章新增API開發並使用Postman測試
系列文
初探全端之旅: 以MERN技術建立個人部落格31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言