我們常常需要在應(yīng)用啟動期間進(jìn)行一些初始化工作,等初始化完成后應(yīng)用才可以啟動成功,并開始對外提供服務(wù)。
框架提供了統(tǒng)一的入口文件(app.js)進(jìn)行啟動過程自定義,這個文件返回一個 Boot 類,我們可以通過定義 Boot 類中的生命周期方法來執(zhí)行啟動應(yīng)用過程中的初始化工作。
框架提供了這些 生命周期函數(shù)供開發(fā)人員處理:
- 配置文件即將加載,這是最后動態(tài)修改配置的時機(jī)(configWillLoad)
- 配置文件加載完成(configDidLoad)
- 文件加載完成(didLoad)
- 插件啟動完畢(willReady)
- worker 準(zhǔn)備就緒(didReady)
- 應(yīng)用啟動完成(serverDidReady)
- 應(yīng)用即將關(guān)閉(beforeClose)
我們可以在 app.js 中定義這個 Boot 類,下面我們抽取幾個在應(yīng)用開發(fā)中常用的生命周期函數(shù)來舉例:
// app.js class AppBootHook { constructor(app) { this.app = app; }
configWillLoad() { // 此時 config 文件已經(jīng)被讀取并合并,但是還并未生效 // 這是應(yīng)用層修改配置的最后時機(jī) // 注意:此函數(shù)只支持同步調(diào)用
// 例如:參數(shù)中的密碼是加密的,在此處進(jìn)行解密 this.app.config.mysql.password = decrypt(this.app.config.mysql.password); // 例如:插入一個中間件到框架的 coreMiddleware 之間 const statusIdx = this.app.config.coreMiddleware.indexOf('status'); this.app.config.coreMiddleware.splice(statusIdx + 1, 0, 'limit'); }
async didLoad() { // 所有的配置已經(jīng)加載完畢 // 可以用來加載應(yīng)用自定義的文件,啟動自定義的服務(wù)
// 例如:創(chuàng)建自定義應(yīng)用的示例 this.app.queue = new Queue(this.app.config.queue); await this.app.queue.init();
// 例如:加載自定義的目錄 this.app.loader.loadToContext(path.join(__dirname, 'app/tasks'), 'tasks', { fieldClass: 'tasksClasses', }); }
async willReady() { // 所有的插件都已啟動完畢,但是應(yīng)用整體還未 ready // 可以做一些數(shù)據(jù)初始化等操作,這些操作成功才會啟動應(yīng)用
// 例如:從數(shù)據(jù)庫加載數(shù)據(jù)到內(nèi)存緩存 this.app.cacheData = await this.app.model.query(QUERY_CACHE_SQL); }
async didReady() { // 應(yīng)用已經(jīng)啟動完畢
const ctx = await this.app.createAnonymousContext(); await ctx.service.Biz.request(); }
async serverDidReady() { // http / https server 已啟動,開始接受外部請求 // 此時可以從 app.server 拿到 server 的實例
this.app.server.on('timeout', socket => { // handle socket timeout }); } }
module.exports = AppBootHook;
|
注意:在自定義生命周期函數(shù)中不建議做太耗時的操作,框架會有啟動的超時檢測。
如果你的 Egg 框架的生命周期函數(shù)是舊版本的,建議你升級到類方法模式;詳情請查看升級你的生命周期事件函數(shù)。
更多建議: