subscribe.js
(function () {
// 全局只有一个事件池
let pond = {};
// 向事件池中订阅方法
const on = function on(type, func) {
if (!pond.hasOwnProperty(type)) pond[type] = [];
let arr = pond[type];
if (arr.includes(func)) return; //去重
arr.push(func);
};
// 从事件池中移除订阅
const off = function off(type, func) {
let arr = pond[type] || [];
if (arr.length === 0) return;
let i = 0,
item;
for (; i < arr.length; i++) {
item = arr[i];
if (item === func) {
// arr.splice(i, 1); //引发数组塌陷
arr[i] = null;
return;
}
}
};
// 通知事件池中,指定类型的方法去执行
const fire = function fire(type, ...params) {
let arr = pond[type] || [],
i = 0,
item;
for (; i < arr.length; i++) {
item = arr[i];
if (typeof item === 'function') {
item(...params);
continue;
}
// 当期这一项不是函数,则我们把其移除掉
arr.splice(i, 1);
i--;
}
};
/* 暴露API */
let sub = {
on,
off,
fire
};
if (typeof window !== 'undefined') window.sub = sub;
//node环境
if (typeof module === 'object' && typeof module.exports === 'object') module.exports = sub;
})();
使用方案如下:
setTimeout(() => {
sub.fire('@A', 100, 200);
}, 1000);
const fn1 = (a, b) => console.log(1, a, b);
const fn2 = () => console.log(2);
sub.on('@A', fn1);
sub.on('@A', fn1);
sub.on('@A', fn2);
submit.onclick = function () {
sub.fire('@A');
};
const fn1 = () => console.log(1);
const fn2 = () => {
console.log(2);
// 第一次执行fn2的同时,从事件池中移除fn1/fn2
sub.off('@A', fn1);
sub.off('@A', fn2);
};
const fn3 = () => console.log(3);
const fn4 = () => console.log(4);
const fn5 = () => console.log(5);
sub.on('@A', fn1);
sub.on('@A', fn2);
sub.on('@A', fn3);
sub.on('@A', fn4);
sub.on('@A', fn5);