mm_os
Version:
MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。
412 lines (388 loc) • 9.13 kB
JavaScript
const Manager = require('mm_machine').Manager;
const Drive = require('./drive');
/**
* Event事件类
* @augments {Manager}
* @class
*/
class Event extends Manager {
/**
* 配置参数
* @type {object}
*/
static config = {
/**
* 名称
* @type {string}
*/
name: '',
/**
* 标题
* @type {string}
*/
title: '事件管理',
/**
* 描述
* @type {string}
*/
description: '这是事件管理器',
/**
* 检索文件名
* @type {string}
*/
filename: 'event.json',
/**
* 模板目录
* @type {string}
*/
tpl_dir: __dirname,
/**
* 基础目录
* @type {string}
*/
base_dir: '../common/event'.fullname(__dirname),
/**
* 自定义目录,加载项目自定义资源
* @type {string}
*/
dir: './app'.fullname(),
/**
* 搜索模式 dir按目录搜索 | file按文件名搜索
* @type {string}
*/
search_way: 'dir',
/**
* 是否懒加载
* @type {boolean}
*/
lazy_load: true,
/**
* 模式
* 1.生产模式,改变文件不会重新加载
* 2.热更新模式,改变配置文件会重新加载配置,不重新加载脚本
* 3.热重载模式,改变配置文件都会加载配置和脚本
* 4.重载模式,执行完后重新加载脚本,避免变量污染
* 5.热更新+重载模式,改变配置文件重新加载配置和脚本,执行完后重新加载脚本
* @type {number}
*/
mode: 3
};
/**
* 构造函数
* @param {object} config 配置参数
* @param {object} parent 父级模块
*/
constructor(config, parent) {
super({ ...Event.config, ...config }, parent);
}
}
/**
* 预设事件
*/
Event.prototype._preset = function () {
// 验证前
this.list_before = [];
// 验证
this.list_check = [];
// 执行
this.list_main = [];
// 渲染
this.list_render = [];
// 渲染后
this.list_after = [];
};
/**
* 事件驱动类
* @type {Drive}
*/
Event.prototype.Drive = Drive;
/**
* 清除事件
* @param {string} stage 阶段
*/
Event.prototype.clear = function (stage) {
if (stage) {
if (this['list_' + stage]) {
this['list_' + stage] = [];
} else {
this.log('debug', '清空失败,事件发展阶段{0}不存在!'.replace('{0}', stage));
}
} else {
this.list_before = [];
this.list_check = [];
this.list_main = [];
this.list_render = [];
this.list_after = [];
}
};
/**
* 更新模块信息
*/
Event.prototype.updateInfo = function () {
for (let name in this.mods) {
let o = this.mods[name];
let info = this.newInfo(name, o.config.sort, o.config.state, o.config_file);
this.pushList(o.config.stage, info);
}
this.sort();
};
/**
* 推送事件信息
* @param {string} stage 阶段
* @param {object} info 事件信息
*/
Event.prototype.pushList = function (stage, info) {
switch (stage) {
case 'before':
this.list_before.push(info);
break;
case 'check':
this.list_check.push(info);
break;
case 'main':
this.list_main.push(info);
break;
case 'render':
this.list_render.push(info);
break;
case 'after':
this.list_after.push(info);
break;
default:
break;
}
};
/**
* 事件排序
*/
Event.prototype._sort = function () {
this._sortSub(this.list_before);
this._sortSub(this.list_check);
this._sortSub(this.list_main);
this._sortSub(this.list_render);
this._sortSub(this.list_after);
};
/**
* 事件排序
* @param {Array} list 列表
*/
Event.prototype._sortSub = function (list) {
var sort_key = this.config.sort_key || 'sort';
list.sort((o1, o2) => {
let s1 = o1[sort_key] || 100;
let s2 = o2[sort_key] || 100;
var cha = s1 - s2;
if (cha === 0) {
let mod1 = this.getMod(o1.name);
let mod2 = this.getMod(o2.name);
if (mod1 && mod2) {
cha = mod2.config.target.length - mod1.config.target.length;
}
}
return cha;
});
};
/**
* 执行事件
* @param {object} o 事件项
* @param {object} ctx 请求上下文
* @param {object} db 数据管理器
* @returns {object} 执行结果
*/
Event.prototype.doing = async function (o, ctx, db) {
var ret = o.run(ctx, db);
if (types.isPromise(ret)) {
ret = await ret;
}
if (this.mode > 4) {
o.do('reload');
}
return ret;
};
/**
* 匹配目标
* @param {string} str 目标
* @param {string} pattern 模式
* @returns {boolean} 是否匹配
*/
Event.prototype.isMatch = function (str, pattern) {
if (str === pattern) {
return true;
} else if (pattern.startsWith('*')) {
let clean = pattern.replaceAll('*', '');
if (pattern.endsWith('*')) {
return str.indexOf(clean) !== -1;
} else {
return str.endsWith(clean);
}
} else if (pattern.endsWith('*')) {
let clean = pattern.replaceAll('*', '');
return str.startsWith(clean);
}
else {
return false;
}
};
/**
* 执行函数
* @param {Array} list 列表
* @param {string} target 目标
* @param {object} ctx 请求上下文
* @param {object} db 数据管理器
* @returns {object} 执行结果
*/
Event.prototype.runSub = async function (list, target, ctx, db) {
for (var i = 0, info; info = list[i++];) {
if (info.state === 1) {
let mod = this.getMod(info.name);
if (mod && this.isMatch(target, mod.config.target)) {
try {
if (!mod.isLoaded()) {
await mod.call('loadScript');
}
var ret = await mod.run(ctx, db);
if (this.mode > 4) {
mod.do('reload');
}
if (ret) {
db.ret = ret;
if (mod.config.end) {
break;
}
}
} catch (error) {
// 事件执行异常时继续执行下一个事件
this.log('error', `事件${info.name}执行失败`, error);
}
}
}
}
return db.ret;
};
/**
* 之前
* @param {string} target 目标
* @param {object} ctx 请求上下文
* @param {object} db 数据管理器
* @returns {object} 执行结果
*/
Event.prototype.before = async function (target, ctx, db) {
return await this.runSub(this.list_before, target, ctx, db);
};
/**
* 验证
* @param {string} target 目标
* @param {object} ctx 请求上下文
* @param {object} db 数据管理器
* @returns {object} 执行结果
*/
Event.prototype.check = async function (target, ctx, db) {
return await this.runSub(this.list_check, target, ctx, db);
};
/**
* 主要
* @param {string} target 目标
* @param {object} ctx 请求上下文
* @param {object} db 数据管理器
* @returns {object} 执行结果
*/
Event.prototype.main = async function (target, ctx, db) {
return await this.runSub(this.list_main, target, ctx, db);
};
/**
* 渲染
* @param {string} target 目标
* @param {object} ctx 请求上下文
* @param {object} db 数据管理器
* @returns {object} 执行结果
*/
Event.prototype.render = async function (target, ctx, db) {
return await this.runSub(this.list_render, target, ctx, db);
};
/**
* 之后
* @param {string} target 目标
* @param {object} ctx 请求上下文
* @param {object} db 数据管理器
* @returns {object} 执行结果
*/
Event.prototype.after = async function (target, ctx, db) {
return await this.runSub(this.list_after, target, ctx, db);
};
/**
* 执行事件
* @param {string} target 目标
* @param {object} ctx 请求上下文
* @param {object} db 数据管理器
* @returns {object} 执行结果
*/
Event.prototype.run = async function (target, ctx, db = {}) {
var ret = await this.before(target, ctx, db);
if (!ret) {
ret = await this.check(target, ctx, db);
if (!ret) {
ret = await this.main(target, ctx, db);
}
ret = await this.render(target, ctx, db);
if (ret) {
ret = await this.after(target, ctx, db);
}
}
return ret;
};
/**
* 获取事件
* @param {string} name 名称
* @param {string} stage 阶段
* @returns {object} 返回单项配置
*/
Event.prototype.get = function (name, stage = 'main') {
var obj;
var lt = this['list_' + stage];
var len = lt.length;
for (var i = 0; i < len; i++) {
var o = lt[i];
if (name === o.config.name) {
obj = o;
break;
}
}
return obj;
};
/**
* @module 导出Event类
*/
exports.Event = Event;
/**
* Event事件池
*/
if (!$.pool.event) {
$.pool.event = {};
}
/**
* Event事件池
* @param {string} scope 作用域
* @param {string} title 标题
* @returns {object} 返回一个事件类
*/
function eventAdmin(scope, title) {
var sc = scope || $.val.scope + '';
var obj = $.pool.event[sc];
if (!obj) {
$.pool.event[sc] = new Event({
name: sc,
title: title,
});
obj = $.pool.event[sc];
}
return obj;
}
/**
* Event管理器,用于创建缓存
* @param {string} scope 作用域
* @param {string} title 标题
* @returns {object} 返回一个缓存类
*/
if ($.admin) {
$.admin.event = eventAdmin;
}