Egg 框架擴展

2020-02-06 14:11 更新

框架提供了多種擴展點擴展自身的功能:

  • Application
  • Context
  • Request
  • Response
  • Helper

在開發(fā)中,我們既可以使用已有的擴展 API 來方便開發(fā),也可以對以上對象進(jìn)行自定義擴展,進(jìn)一步加強框架的功能。

Application

app 對象指的是 Koa 的全局應(yīng)用對象,全局只有一個,在應(yīng)用啟動時被創(chuàng)建。

訪問方式

  • ctx.app
  • Controller,Middleware,Helper,Service 中都可以通過 this.app 訪問到 Application 對象,例如 this.app.config 訪問配置對象。
  • 在 app.js 中 app 對象會作為第一個參數(shù)注入到入口函數(shù)中// app.jsmodule.exports = app => { // 使用 app 對象};

擴展方式

框架會把 app/extend/application.js 中定義的對象與 Koa Application 的 prototype 對象進(jìn)行合并,在應(yīng)用啟動時會基于擴展后的 prototype 生成 app 對象。

方法擴展

例如,我們要增加一個 app.foo() 方法:

// app/extend/application.js
module.exports = {
foo(param) {
// this 就是 app 對象,在其中可以調(diào)用 app 上的其他方法,或訪問屬性
},
};

屬性擴展

一般來說屬性的計算只需要進(jìn)行一次,那么一定要實現(xiàn)緩存,否則在多次訪問屬性時會計算多次,這樣會降低應(yīng)用性能。

推薦的方式是使用 Symbol + Getter 的模式。

例如,增加一個 app.bar 屬性 Getter:

// app/extend/application.js
const BAR = Symbol('Application#bar');

module.exports = {
get bar() {
// this 就是 app 對象,在其中可以調(diào)用 app 上的其他方法,或訪問屬性
if (!this[BAR]) {
// 實際情況肯定更復(fù)雜
this[BAR] = this.config.xx + this.config.yy;
}
return this[BAR];
},
};

Context

Context 指的是 Koa 的請求上下文,這是 請求級別 的對象,每次請求生成一個 Context 實例,通常我們也簡寫成 ctx。在所有的文檔中,Context 和 ctx 都是指 Koa 的上下文對象。

訪問方式

  • middleware 中 this 就是 ctx,例如 this.cookies.get('foo')。
  • controller 有兩種寫法,類的寫法通過 this.ctx,方法的寫法直接通過 ctx 入?yún)ⅰ?/li>
  • helper,service 中的 this 指向 helper,service 對象本身,使用 this.ctx 訪問 context 對象,例如 this.ctx.cookies.get('foo')。

擴展方式

框架會把 app/extend/context.js 中定義的對象與 Koa Context 的 prototype 對象進(jìn)行合并,在處理請求時會基于擴展后的 prototype 生成 ctx 對象。

方法擴展

例如,我們要增加一個 ctx.foo() 方法:

// app/extend/context.js
module.exports = {
foo(param) {
// this 就是 ctx 對象,在其中可以調(diào)用 ctx 上的其他方法,或訪問屬性
},
};

屬性擴展

一般來說屬性的計算在同一次請求中只需要進(jìn)行一次,那么一定要實現(xiàn)緩存,否則在同一次請求中多次訪問屬性時會計算多次,這樣會降低應(yīng)用性能。

推薦的方式是使用 Symbol + Getter 的模式。

例如,增加一個 ctx.bar 屬性 Getter:

// app/extend/context.js
const BAR = Symbol('Context#bar');

module.exports = {
get bar() {
// this 就是 ctx 對象,在其中可以調(diào)用 ctx 上的其他方法,或訪問屬性
if (!this[BAR]) {
// 例如,從 header 中獲取,實際情況肯定更復(fù)雜
this[BAR] = this.get('x-bar');
}
return this[BAR];
},
};

Request

Request 對象和 Koa 的 Request 對象相同,是 請求級別 的對象,它提供了大量請求相關(guān)的屬性和方法供使用。

訪問方式

ctx.request

ctx 上的很多屬性和方法都被代理到 request 對象上,對于這些屬性和方法使用 ctx 和使用 request 去訪問它們是等價的,例如 ctx.url === ctx.request.url。

Koa 內(nèi)置的代理 request 的屬性和方法列表:Koa - Request aliases

擴展方式

框架會把 app/extend/request.js 中定義的對象與內(nèi)置 request 的 prototype 對象進(jìn)行合并,在處理請求時會基于擴展后的 prototype 生成 request 對象。

例如,增加一個 request.foo 屬性 Getter:

// app/extend/request.js
module.exports = {
get foo() {
return this.get('x-request-foo');
},
};

Response

Response 對象和 Koa 的 Response 對象相同,是 請求級別 的對象,它提供了大量響應(yīng)相關(guān)的屬性和方法供使用。

訪問方式

ctx.response

ctx 上的很多屬性和方法都被代理到 response 對象上,對于這些屬性和方法使用 ctx 和使用 response 去訪問它們是等價的,例如 ctx.status = 404 和 ctx.response.status = 404 是等價的。

Koa 內(nèi)置的代理 response 的屬性和方法列表:Koa Response aliases

擴展方式

框架會把 app/extend/response.js 中定義的對象與內(nèi)置 response 的 prototype 對象進(jìn)行合并,在處理請求時會基于擴展后的 prototype 生成 response 對象。

例如,增加一個 response.foo 屬性 setter:

// app/extend/response.js
module.exports = {
set foo(value) {
this.set('x-response-foo', value);
},
};

就可以這樣使用啦:this.response.foo = 'bar';

Helper

Helper 函數(shù)用來提供一些實用的 utility 函數(shù)。

它的作用在于我們可以將一些常用的動作抽離在 helper.js 里面成為一個獨立的函數(shù),這樣可以用 JavaScript 來寫復(fù)雜的邏輯,避免邏輯分散各處。另外還有一個好處是 Helper 這樣一個簡單的函數(shù),可以讓我們更容易編寫測試用例。

框架內(nèi)置了一些常用的 Helper 函數(shù)。我們也可以編寫自定義的 Helper 函數(shù)。

訪問方式

通過 ctx.helper 訪問到 helper 對象,例如:

// 假設(shè)在 app/router.js 中定義了 home router
app.get('home', '/', 'home.index');

// 使用 helper 計算指定 url path
ctx.helper.pathFor('home', { by: 'recent', limit: 20 })
// => /?by=recent&limit=20

擴展方式

框架會把 app/extend/helper.js 中定義的對象與內(nèi)置 helper 的 prototype 對象進(jìn)行合并,在處理請求時會基于擴展后的 prototype 生成 helper 對象。

例如,增加一個 helper.foo() 方法:

// app/extend/helper.js
module.exports = {
foo(param) {
// this 是 helper 對象,在其中可以調(diào)用其他 helper 方法
// this.ctx => context 對象
// this.app => application 對象
},
};

按照環(huán)境進(jìn)行擴展

另外,還可以根據(jù)環(huán)境進(jìn)行有選擇的擴展,例如,只在 unittest 環(huán)境中提供 mockXX() 方法以便進(jìn)行 mock 方便測試。

// app/extend/application.unittest.js
module.exports = {
mockXX(k, v) {
}
};

這個文件只會在 unittest 環(huán)境加載。

同理,對于 Application,Context,Request,Response,Helper 都可以使用這種方式針對某個環(huán)境進(jìn)行擴展,更多參見運行環(huán)境


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號