UNPKG

mm_os

Version:

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

405 lines (376 loc) 9.66 kB
const Item = require('mm_machine').Drive; /** * 延迟 * @param {number} milli_seconds 毫秒 */ function sleep(milli_seconds) { var end_time = new Date().getTime() + milli_seconds; while (new Date().getTime() < end_time) { } } /** * 计算时间差 * @param {string} start_time 开始时间 * @param {string} end_time 结束时间 * @returns {number} 返回间隔时长 */ function span(start_time, end_time) { var stime = Date.parse(start_time); var etime = Date.parse(end_time); return etime - stime; }; /** * 转为时间 * @param {string} time_str 时间字符串 * @returns {Date} 时间类型 */ function toTime(time_str) { var str = time_str.replace('T', ' ').replace('Z', '').replaceAll('.', '/').replaceAll('-', '/'); return new Date(str); }; /** * 定时器类函数 */ class Drive extends Item { static config = { // 应用名称 例如:demo_app 'app': 'server', // 插件名称 例如:demo_plugin 'plugin': 'sys', // 执行次数 'num': 10, // 时间间隔(毫秒ms) 'interval': 1000, // 等待时长(毫秒ms) 'wait': 0, // 执行时间 'time': '', // 执行开始日期 'date_start': '', // 执行结束日期 'date_end': '' }; /** * 构造函数 * @param {object} config 配置参数 * @param {object} parent 父对象 * @class */ constructor(config, parent) { super({ ...Drive.config, ...config }, parent); // 更新配置并重载脚本 this.mode = 3; } } /** * 预设 */ Drive.prototype._preset = function () { /// 状态 this.state = 'start'; /// 等候器 this.timeout; /// 定时执行器 this.interval; /// 当前执行次数 this.num = 1; }; /** * 设置等待执行 * @param {Function} func 回调函数 */ Drive.prototype.setTimeout = function (func) { if (func) { this.timeout = setTimeout(func, this.config.wait); } }; /** * 设置间隔执行 * @param {Function} func 回调函数 */ Drive.prototype.setInterval = async function (func) { sleep(this.config.wait); this.interval = setInterval(func, this.config.interval); }; /** * 创建时间匹配函数 * @param {string} time 时间字符串 * @param {Function} func 回调函数 * @returns {Function} 时间匹配函数 */ Drive.prototype._createTimeFn = function (time, func) { if (!time) return func; if (time.indexOf(' ') !== -1) { return this._createDateTimeFn(time, func); } return this._createTimeOnlyFn(time, func); }; /** * 创建日期时间匹配函数 * @param {string} time 时间字符串 * @param {Function} func 回调函数 * @returns {Function} 时间匹配函数 */ Drive.prototype._createDateTimeFn = function (time, func) { if (time.indexOf('-') !== -1) { var arr = time.split('-'); var fmt = arr.length > 2 ? 'yyyy-MM-dd hh:mm:ss' : 'MM-dd hh:mm:ss'; return function () { if (new Date().toStr(fmt) === time) func(); }; } var arr = time.split(':'); var fmt = arr.length == 3 ? 'dd hh:mm:ss' : (arr.length == 2 ? 'dd hh:mm' : 'dd hh'); return function () { if (new Date().toStr(fmt) === time) func(); }; }; /** * 创建仅时间匹配函数 * @param {string} time 时间字符串 * @param {Function} func 回调函数 * @returns {Function} 时间匹配函数 */ Drive.prototype._createTimeOnlyFn = function (time, func) { var arr = time.split(':'); var fmt = arr.length == 3 ? 'hh:mm:ss' : (arr.length == 2 ? 'hh:mm' : 'mm'); return function () { if (new Date().toStr(fmt) === time) func(); }; }; /** * 创建带开始时间的执行函数 * @param {Function} fn 原始函数 * @param {number} start 开始时间 * @param {number} end 结束时间 * @returns {Function} 执行函数 */ Drive.prototype._createStartFn = function (fn, start, end) { var _this = this; if (end) { return function () { var now = new Date(); if (span(now, end) >= 0 && span(now, start) <= 0) fn(); else if (span(now, end) < 0) { _this.clearSub(); _this.notify(_this.config.name, 'time_end'); } }; } return function () { if (span(new Date(), start) <= 0) fn(); }; }; /** * 创建带结束时间的执行函数 * @param {Function} fn 原始函数 * @param {number} end 结束时间 * @returns {Function} 执行函数 */ Drive.prototype._createEndFn = function (fn, end) { var _this = this; return function () { if (span(new Date(), end) >= 0) fn(); else { _this.clearSub(); _this.notify(_this.config.name, 'time_end'); } }; }; /** * 设置时期执行 * @param {Function} func 回调函数 * @returns {object} 执行结果 */ Drive.prototype.setPeriod = function (func) { var cg = this.config; var fn = this._createTimeFn(cg.time, func); if (cg.date_start) { return this._createStartFn(fn, toTime(cg.date_start), cg.date_end ? toTime(cg.date_end) : null); } if (cg.date_end) { return this._createEndFn(fn, toTime(cg.date_end)); } return fn; }; /** * 设置按次数执行 * @param {Function} func 回调函数 * @returns {object} 执行结果 */ Drive.prototype.setNum = function (func) { var _this = this; return function () { if (_this.state === 'start') { try { if (_this.config.num < 1) { func(); } else if (_this.num < _this.config.num) { func(); _this.num += 1; } else { func(); _this.clear(); _this.notify(_this.config.name, 'completed'); } } catch (err) { _this.log('error', '定时任务执行失败!', _this.config.name, err); } } }; }; /** * 结束定时器 */ Drive.prototype.end = function () { // 当前状态为结束 this.state = 'end'; this.notify(this.config.name, 'suspend'); this.clear(); }; /** * 清除定时器(子函数) */ Drive.prototype.clearSub = function () { if (this.interval) { clearInterval(this.interval); } if (this.timeout) { clearTimeout(this.timeout); } }; /** * 清除定时器 * @param {number} millisecond 时间间隔, 单位: 毫秒 */ Drive.prototype.clear = function (millisecond) { if (millisecond) { var _this = this; setTimeout(() => { _this.clearSub(); }, millisecond); } else { this.clearSub(); } }; /** * 执行线程 * @returns {object} 当前类 */ Drive.prototype.main = async function () { this.log('debug', '定时任务(默认), 执行中...'); }; /** * 执行线程 * @param {Function} func 回调函数 * @returns {object} 当前类 */ Drive.prototype.run = async function (func) { this.init(); if (func) { await this.setInterval(this.setPeriod(this.setNum(func))); } else { await this.setInterval(this.setPeriod(this.setNum(() => { this.main(); }))); } return this; }; /** * 初始化定时器 */ Drive.prototype.init = function () { // 当前执行次数 this.num = 1; // 当前状态为开启 this.state = 'start'; this.notify(this.config.name, 'init'); }; /** * 启动定时器 */ Drive.prototype.start = function () { // 当前状态为开启 this.state = 'start'; this.notify(this.config.name, 'start'); }; /** * 暂停定时器 */ Drive.prototype.stop = function () { // 当前状态为开启 this.state = 'stop'; this.notify(this.config.name, 'stop'); }; /** * 通知函数, 当定时器执行完最后一次时, 会调用通知函数 * @param {string} name 名称 * @param {string} state 状态 */ Drive.prototype.notify = function (name, state) { // switch (state) { // case "init": // this.log('debug', '初始化'); // break; // case "start": // this.log('debug', '开始执行'); // break; // case "stop": // this.log('debug', '已暂停'); // break; // case "suspend": // // 主动中断 // this.log('debug', '已中断'); // break; // case "time_end": // this.log('debug', '已到期'); // break; // case "completed": // this.log('debug', '已完成'); // break; // default: // break; // } }; /** * 销毁资源 */ Drive.prototype.dispose = function () { this.clearSub(); this.interval = undefined; this.timeout = undefined; }; /** * 获取插件 * @param {string} app 应用名称 * @param {string} name 插件名称 * @returns {object} 返回获取到的插件 */ Drive.prototype.plugin = function (app, name) { var l = $.slash; var app_name = app || this.config_file.between('app' + l, l); var plugin_name = name || this.config_file.between('plugin' + l, l); var plus; var plugins = $.pool.plugin[app_name]; if (plugins) { plus = plugins.get(plugin_name); } return plus; }; /** * 获取模型 * @param {string} type 模型类型 * @returns {object} 返回获取到的模型 */ Drive.prototype.getModel = function (type) { let model = { ...this.config }; let dir = this.getDir(); let l = $.slash; let app_name = dir.between('app' + l, l); let plugin_name = dir.between('plugin' + l, l); let name = dir.basename(); model.app = app_name; model.plugin = plugin_name; model.name = model.name || app_name + '_' + name; return model; }; module.exports = Drive;