UNPKG

mm_os

Version:

MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。

412 lines (388 loc) 9.13 kB
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; }