Egg 中 Controller 最佳實踐

来源:https://www.cnblogs.com/zhang740/archive/2018/08/20/9506495.html
-Advertisement-
Play Games

得益於 JavaScript 加入的 decorator 特性,可以使我們跟 Java/C 一樣,更加直觀自然的,做面向切麵編程。而隨著 TypeScript 的成熟,類型系統也讓我們增強了信心,面對複雜的業務邏輯,也更有底氣。 "egg controller" 是集合了一些在 Controller ...


得益於 JavaScript 加入的 decorator 特性,可以使我們跟 Java/C# 一樣,更加直觀自然的,做面向切麵編程。而隨著 TypeScript 的成熟,類型系統也讓我們增強了信心,面對複雜的業務邏輯,也更有底氣。

egg-controller 是集合了一些在 Controller 層開發中常見問題解決方案的插件。

Controller 路由定義

export class HomeController {
  @route('/api/xxx', { name: '獲取XXX數據' })
  async getXXX(size: number, page: number) {
    return 'homeIndex';
  }
}

可以看到,使用 decorator 的形式來聲明 Controller 非常直觀,而且方便擴展,添加/修改 Controller 規則直接修改 decorator 的類型定義就好。這種形式也是 Java/C# 的常規操作。

這裡的改進除了使用 decorator 替代了 router.js 來進行 Controller 聲明以外,還添加了出入參支持,省去了需要手動讀寫 ctx 的過程,非常直觀的聲明 Controller 函數的參數需求,以及返回數據類型。

基於 decorator 的寫法與之前最大的區別是,在 Controller 這個橫切麵,之前只有 loader 可以掌控,而現在可以在 decorator 中加以集中控制,再結合 TypeScript 的元信息,可以做出很多擴展,比如:

參數格式化

在 eggjs 中,因為沒有類型信息的原因,從 params 和 query 中獲取的信息都會是字元串類型,都需要在 Controller 中手動轉換。而改造之後的寫法,參數直接暴露在函數入參里,我們就可以直接拿寫在入參的類型定義作為格式化的依據,根據類型嘗試轉換,保證參數類型正確,可以初步防止類型不符的參數進入到 Controller,省去手動判斷、轉換的邏輯。

參數校驗

參數格式化只能保證參數的類型一致性,而我們的需求不止這些,比如必選參數為空時需要攔截,有時參數是複雜對象為了防止惡意構造數據,需要對數據格式做深度檢測,所以這裡引入了參數校驗庫,parameter,通過它來解決複雜的校驗問題。

export class HomeController {
  @route('/api/xxx', { name: '獲取XXX數據', validateMetaInfo: [{
    name: 'data',
    rule: {
      type: 'object',
      str: { type: 'string', max: 20 },
      count: { type: 'number', max: 10, required: false },
    },
   }] })
  async getXXX(data: { str: string, count?: number }>) {
    return data.str;
  }
}

這裡有個問題,在類型是複雜類型時,TypeScript 預設生成的元數據里,獲取不到類型的具體欄位屬性信息,而且前端直接引入復用後端的類型定義也比較麻煩。所以,想要在定義類型的同時,復用類型的定義,只能在編譯時做工作,TypeScript 也開放出了編譯時插件API,在不用編譯時插件的情況下,就需要單獨寫一份規則的數據。

有插件後:

export class HomeController {
  @route('/api/xxx', { name: '獲取XXX數據' })
  async getXXX(data: BaseValidateRule<{
    type: 'object',
    rule: {
      str: { type: 'string', max: 20 },
      count: { type: 'number', max: 10, required: false },
    },
  }>) {
    return data.str;
  }
}

路由級中間件

函數類型跟 egg 定義稍有不同:

(app: Application, typeInfo: RouteType) => (ctx: any, next: any) => any

egg 已經定義了中間件,為什麼在路由上還定義一個?在路由定義的中間件跟全局的中間件區別在於範圍,全局中間件更適合大規模的統一處理,用來統一處理特定業務功能介面就大材小用了,還需要設置過濾邏輯,甚至需要在 config 中設置黑白名單。而路由級中間件適合只有部分介面需要的統一處理,配合從 @route 上收集的類型信息處理更佳。

API文檔 & 前端SDK

既然已經收集到了那麼多元數據,根據這些數據生成API文檔就很簡單了無非就是前端的展示,也可以把數據轉換對接其他的API文檔平臺。

更近一步,直接生成前端調用SDK?當然沒問題。本插件支持通過模板生成,如果沒有找到模板,會在SDK生成目錄生成預設模板。

// Controller
export class MetaController {

  @route({ url: '/meta/index', name: '首頁' })
  async index(id: string, n: number, e: 'enumA' | 'enumB', d: Date) {
    return 'metaIndex';
  }

}

// 生成代碼
export class MetaService extends Base {

  /** 首頁  */
  async index(id: string, n: number, e: string, d: Date) {
    const __data = { id, n, e, d };
    return await this.request({
      method: `get`,
      url: `/meta/index`,
      data: __data,
    });
  }

}

export const metaService = new MetaService();
export default new MetaService();

開發時

在配置中開啟即可,根據需要自定義其他配置。當 Controller 中文件修改時,會同時重新生成對應的前端SDK文件。

構建打包時

在 前端打包流程前 可以使用 egg-controller gensdk 命令生成前端sdk,需要註意,如果為 TypeScript 項目,需要先將 TypeScript 編譯,然後執行生成命令。

Controller 作為請求的起點,這隻是個開始。

egg 框架

egg-controller 詳細文檔


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • angularjs學習筆記,系統學習整理angular。angularjs、$scope、$parse、$interpolate ...
  • 這個系列將從基礎語法講起,把react全家桶都講到,然後到具體的使用,最後完成後,會寫一個完整的demo。 前置要求: 基本的CSS,JS要熟練。 部分ES6語法需要瞭解。可以參考下麵提到的阮一峰老師的《ECMAScript 6 入門》和MDN文檔。 目前已經完成的內容: "react教程(零)安裝 ...
  • CSS3實現各種表情 效果圖: 代碼如下,複製即可使用: 如有錯誤,歡迎聯繫我改正,非常感謝!!! ...
  • 最近剛剛看完了《你不知道的 JavaScript》上捲,對 JavaScript 有了更進一步的瞭解。 《你不知道的 JavaScript》上捲由兩部分組成,第一部分是《作用域和閉包》,第二部分是《this 和對象原型》。下麵我會按照簡單介紹一下每一章的主要內容及閱讀感受。 第一部分《作用域和閉包》 ...
  • 最近學習了 HTML5 中的重頭戲 。利用 canvas,前端人員可以很輕鬆地、進行圖像處理。其 API 繁多,這次主要學習常用的 API,並且完成以下兩個代碼: 1. 實現去色濾鏡 2. 實現負色(反色)濾鏡 歡迎入群:_857989948_ 。IT 技術深度交流和分享,涉及方麵包括但不限於:網站 ...
  • jQuery中常用的事件: blur:失去焦點 focus:獲取焦點 click:點擊事件 keydown:鍵盤按下的事件 keyup:鍵盤按下鬆開後的事件 mousemove:滑鼠移動事件 hover:滑鼠懸浮事件 mousedown:滑鼠按下發生的事件 mouseup:滑鼠按下鬆開發生的事件 . ...
  • 1、實現動態圖片的切換隻需要改變目標圖片的路徑 ...
  • FormData格式提交的post參數可以直接從req.body里取,而axios用request payload,req.body都是空對象。 百度一圈,全是你抄我我抄你,要麼讓你繞路用contentType+JSON.stringfy,要麼就res.on流讀取請求數據,一點都不優雅好麽。其實沒那 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...