mm_os
Version:
MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。
405 lines (376 loc) • 9.66 kB
JavaScript
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;