mm_os
Version:
MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。
352 lines (328 loc) • 8.24 kB
JavaScript
const Manager = require('mm_machine').Manager;
const Drive = require('./drive');
/**
* 任务类
* @augments {Manager}
* @class
*/
class Socket extends Manager {
/**
* 配置参数
* @type {object}
*/
static config = {
/**
* 名称
* @type {string}
*/
name: '',
/**
* 标题
* @type {string}
*/
title: 'socket管理',
/**
* 描述
* @type {string}
*/
description: '这是socket管理器',
/**
* 检索文件名
* @type {string}
*/
filename: 'socket.json',
/**
* 模板目录
* @type {string}
*/
tpl_dir: __dirname,
/**
* 基础目录
* @type {string}
*/
base_dir: '../common/socket'.fullname(__dirname),
/**
* 自定义目录,加载项目自定义资源
* @type {string}
*/
dir: './app'.fullname(),
/**
* 搜索模式 dir按目录搜索 | file按文件名搜索
* @type {string}
*/
search_way: 'file',
/**
* 是否懒加载
* @type {boolean}
*/
lazy_load: true,
/**
* 模式
* 1.生产模式,改变文件不会重新加载
* 2.热更新模式,改变配置文件会重新加载配置,不重新加载脚本
* 3.热重载模式,改变配置文件都会加载配置和脚本
* 4.重载模式,执行完后重新加载脚本,避免变量污染
* 5.热更新+重载模式,改变配置文件重新加载配置和脚本,执行完后重新加载脚本
* @type {number}
*/
mode: 3
};
/**
* 构造函数
* @param {object} config 配置参数
* @param {object} parent 父级模块
*/
constructor(config, parent) {
super({ ...Socket.config, ...config }, parent);
this.dict = {};
/**
* 消息队列
*/
this.list_msg = [
/*
{
// 消息ID
id: "",
// 请求方法
method: "",
// 消息参数
params: {},
// 回调函数
func: function(res){},
// 时间戳
timestamp: 0,
// 超时时间
timeout: 0,
// 定时器
timer: null
}
*/
];
}
}
/**
* socket驱动类
* @type {Drive}
*/
Socket.prototype.Drive = Drive;
/**
* 处理socket请求
* @param {object} ctx 请求上下文
* @param {Function} next 跳过当前, 然后继续执行函数
*/
Socket.prototype.run = async function (ctx, next) {
await next();
let path = ctx.path.toLocaleLowerCase();
var infos = this.getInfos();
for (var i = 0, info; info = infos[i++];) {
// console.log("监听webscoket路径是否正确", path === info.path);
if (info.state === 1) {
let mod = this.getMod(info.name);
if (path === info.path) {
if (mod) {
mod.add(ctx);
}
break;
}
}
}
};
/**
* 发送消息到指定客户端
* @param {string} client_id 客户端ID
* @param {string} method 方法名称
* @param {object} params 请求参数
* @returns {boolean} 发送是否成功
*/
Socket.prototype.send = function (client_id, method, params) {
var mods = this.getMods();
for (var k in mods) {
var o = mods[k];
if (o.config.state === 1 && o.send) {
// 设置管理器引用,用于消息回复处理
o.manager = this;
return o.send(client_id, method, params);
}
}
return false;
};
/**
* 发送消息到所有连接的客户端
* @param {string} method 方法名称
* @param {object} params 请求参数
*/
Socket.prototype.sendAll = function (method, params) {
var mods = this.getMods();
for (var k in mods) {
var o = mods[k];
if (o.config.state === 1 && o.sendAll) {
// 设置管理器引用,用于消息回复处理
o.manager = this;
o.sendAll(method, params);
}
}
};
/**
* 发送请求到指定客户端
* @param {string} client_id 客户端ID
* @param {string} method 方法名称
* @param {object} params 请求参数
* @param {Function} func 回调函数
* @param {number} timeout 超时时间(毫秒)
* @returns {boolean} 发送是否成功
*/
Socket.prototype.req = function (client_id, method, params, func, timeout = 0) {
var mods = this.getMods();
for (var k in mods) {
var o = mods[k];
if (o.config.state === 1 && o.req) {
// 设置管理器引用,用于消息回复处理
o.manager = this;
return o.req(client_id, method, params, func, timeout);
}
}
return false;
};
/**
* 发送请求到所有连接的客户端
* @param {string} method 方法名称
* @param {object} params 请求参数
* @param {Function} func 回调函数
* @param {number} timeout 超时时间(毫秒)
*/
Socket.prototype.reqAll = function (method, params, func, timeout = 0) {
var mods = this.getMods();
for (var k in mods) {
var o = mods[k];
if (o.config.state === 1 && o.reqAll) {
// 设置管理器引用,用于消息回复处理
o.manager = this;
o.reqAll(method, params, func, timeout);
}
}
};
/**
* 同步请求到指定客户端 - 可及时取回消息
* @param {string} client_id 客户端ID
* @param {string} method 请求方法
* @param {object} params 传递参数
* @param {number} timeout 超时时间(毫秒)
* @returns {Promise} 返回响应结果的Promise
*/
Socket.prototype.reqAsync = function (client_id, method, params, timeout = 0) {
var _this = this;
return new Promise((resolve, reject) => {
_this.req(client_id, method, params, (res) => {
resolve(res);
}, timeout);
});
};
/**
* 同步请求到所有客户端 - 可及时取回消息
* @param {string} method 请求方法
* @param {object} params 传递参数
* @param {number} timeout 超时时间(毫秒)
* @returns {Promise} 返回响应结果的Promise
*/
Socket.prototype.reqAsyncAll = function (method, params, timeout = 0) {
var _this = this;
return new Promise((resolve, reject) => {
_this.reqAll(method, params, (res) => {
resolve(res);
}, timeout);
});
};
/**
* 生成消息ID
* @returns {string} 消息ID
* @private
*/
Socket.prototype._genId = function () {
return 'socket_' + Date.parse(new Date()) + '_' + Math.random().toString(36).substr(2, 9);
};
/**
* 根据ID移除消息
* @param {string} msg_id 消息ID
* @private
*/
Socket.prototype._delMsgById = function (msg_id) {
for (var i = 0; i < this.list_msg.length; i++) {
if (this.list_msg[i].id === msg_id) {
// 清除定时器
if (this.list_msg[i].timer) {
clearTimeout(this.list_msg[i].timer);
}
this.list_msg.splice(i, 1);
break;
}
}
};
/**
* 处理消息回复
* @param {object} msg 回复消息
* @private
*/
Socket.prototype._handleResponse = function (msg) {
if (!msg || !msg.id) {
return;
}
for (var i = 0; i < this.list_msg.length; i++) {
let o = this.list_msg[i];
if (o.id === msg.id && o.func) {
try {
// 执行回调函数
o.func(msg);
} catch (error) {
console.error('Socket回调函数执行错误:', error);
}
// 从列表中移除已处理的消息
this._delMsgById(o.id);
break;
}
}
};
/**
* 更新加载插件
* @param {string} path 检索路径
*/
Socket.prototype.updateConfigAll = async function (path) {
var p = path || './app/';
// 获取所有应用路径
var list_scope = $.dir.getAll(p, 'socket');
// 遍历目录路径
for (var i = 0, f; f = list_scope[i++];) {
var list_file = $.file.getAll(f, '*' + this.type + '.json');
await this.loadList(list_file);
}
};
exports.Socket = Socket;
/**
* Socket组件池
*/
if (!$.pool.socket) {
$.pool.socket = {};
}
/**
* Socket管理器,用于创建缓存
* @param {string} scope 作用域
* @param {string} title 标题
* @returns {object} 返回一个缓存类
*/
function socketAdmin(scope, title) {
var sc = scope || $.val.scope + '';
var obj = $.pool.socket[sc];
if (!obj) {
$.pool.socket[sc] = new Socket({
name: sc,
title: title
});
obj = $.pool.socket[sc];
}
return obj;
}
/**
* @module 导出Socket管理器
*/
if ($.admin) {
$.admin.socket = socketAdmin;
}