一、中介者简介
功能:订阅、发布、取消订阅、取消发布
基本使用方式:
- 订阅:$intermediary.subscribe(“header”,“username”,function (username) {});
- 发布:$intermediary.publish(“header”,“username”,“hang”);
- 取消订阅:$intermediary.cancelSubscribe(“header”,“username”,fn);
- 取消发布:$intermediary.cancelPublish(“header”,“username”,“hang”);
整体架构:
- 订阅信息 > 命名空间 > 信息名 > 回调函数
- 发布信息 > 命名空间 > 信息名 > 内容
- 都是一对多的关系
注意点:
- 订阅只能接收指定 命名空间 和 信息名 发布的信息
- 订阅可以在发布前,也可在发布后,如果在发布后订阅的,默认无法接收到之前的内容,如果想接收,需要在形参最后加上一个 true
例如:$intermediary.subscribe(“header”,“username”,function (username) {},true); - 取消订阅 和 取消发布 可以传任意的参数,将会删除任意的节点
例如:$intermediary.cancelSubscribe(“header”);
将会删除订阅信息中 “header” 的命名空间,同样,传两个参数,则会删除指定的信息名 - 如果删除的不存在 或 没有传参,则会返回 false ,默认返回 true
- 回调函数 和 内容 都可重复
- 回调函数 和 内容 都会一直保存,不需要时,及时删除
二、实现代码
const $intermediary = (function () {
/*订阅队列*/
const subscriptionQueue = {};
/*发布队列*/
const publishQueue = {};
/*创建命名空间,不同的模块使用不同的命名空间,方便维护*/
const createNameSpace = function (nameSpace,queue) {
queue[nameSpace] = queue[nameSpace] || {};
}
/*创建信息名,在指定队列和命名空间下创建信息名*/
const createMsgName = function (msgName,nameSpace,queue) {
createNameSpace(nameSpace,queue);
queue[nameSpace][msgName] = queue[nameSpace][msgName] || [];
}
/*删除属性名,除了回调函数和内容用数组保存,其他都为对象,调用此方法删除*/
const deletePropertyName = function (obj,propertyName) {
let hasPropertyName = false;
for (let index in obj) {
if (index === propertyName) {
hasPropertyName = true;
delete obj[propertyName];
}
}
return hasPropertyName;
}
/*删除元素,回调函数和内容用数组保存,调用此方法删除*/
const deleteEl = function (arr,el) {
let hasEl = false;
arr.forEach((value,index) => {
if (value === el) {
hasEl = true;
arr.splice(index,1);
}
})
return hasEl;
}
/*删除命名空间*/
const deleteNameSpace = function (nameSpace,queue) {
return deletePropertyName(queue,nameSpace);
}
/*删除信息名*/
const deleteMsgName = function (nameSpace,msgName,queue) {
if (queue[nameSpace]) {
return deletePropertyName(queue[nameSpace],msgName);
}
return false;
}
/*删除回调函数*/
const deleteCallback = function (nameSpace,msgName,callback) {
if (subscriptionQueue?.[nameSpace]?.[msgName]) {
return deleteEl(subscriptionQueue[nameSpace][msgName],callback);
}
return false;
}
/*删除内容*/
const deleteContent = function (nameSpace,msgName,content) {
if (publishQueue?.[nameSpace]?.[msgName]) {
return deleteEl(publishQueue[nameSpace][msgName],content);
}
return false;
}
/*执行新的信息队列,当发布消息时,将会执行所有对应的回调函数*/
const implementNewMsg = function (nameSpace,msgName,content) {
publishQueue[nameSpace][msgName].push(content);
if (subscriptionQueue?.[nameSpace]?.[msgName]) {
for (let fn of subscriptionQueue[nameSpace][msgName]) {
fn(content);
}
}
}
/*执行旧的信息队列,当后订阅的回调函数想输出以前的内容,将会遍历所有对应内容,并执行此回调函数*/
const implementOldMsg = function (nameSpace,msgName,callback){
if (publishQueue?.[nameSpace]?.[msgName]) {
for (let content of publishQueue[nameSpace][msgName]) {
callback(content);
}
}
}
/*订阅
* nameSpace: 命名空间,如果没有,则会在订阅队列中新建新建
* msgName:信息名,如果没有,则会在订阅队列指定命名空间中新建
* callback:回调函数,发布对应消息时,将会执行,可以重复,可接受一个参数,为对应的内容
* oldMsg: 是否接收在订阅前发布的内容,true/false
*/
const subscribe = function (nameSpace,msgName,callback,oldMsg) {
createMsgName(msgName,nameSpace,subscriptionQueue);
subscriptionQueue[nameSpace][msgName].push(callback) ;
!!oldMsg && (implementOldMsg)(nameSpace,msgName,callback);
}
/*发布
* nameSpace: 命名空间,如果没有,则会在发布队列中新建新建
* msgName:信息名,如果没有,则会在发布队列指定命名空间中新建
* content: 内容,可以重复
* */
const publish = function (nameSpace,msgName,content) {
createMsgName(msgName,nameSpace,publishQueue);
implementNewMsg(nameSpace,msgName,content);
}
/*取消订阅,根据传入形参的个数,决定删除的层级*/
const cancelSubscribe = function (nameSpace,msgName,callback) {
if (callback) {
return (deleteCallback)(nameSpace,msgName,callback);
} else if (msgName) {
return (deleteMsgName)(nameSpace,msgName,subscriptionQueue);
} else if (nameSpace) {
return (deleteNameSpace)(nameSpace,subscriptionQueue);
} else {
return false;
}
}
/*取消发布,根据传形参的个数,决定删除的层级*/
const cancelPublish = function (nameSpace,msgName,content) {
if (content) {
return (deleteContent)(nameSpace,msgName,content);
} else if (msgName) {
return (deleteMsgName)(nameSpace,msgName,publishQueue);
} else if (nameSpace) {
return (deleteNameSpace)(nameSpace,publishQueue);
} else {
return false;
}
}
return {
subscribe,
publish,
cancelSubscribe,
cancelPublish,
[Symbol.toPrimitive] (hint) {
return hint === 'string' ? '自定义' : true;
}
}
})()
//export default $intermediary