subscribe.js
    2-1.png

    1. (function () {
    2. // 全局只有一个事件池
    3. let pond = {};
    4. // 向事件池中订阅方法
    5. const on = function on(type, func) {
    6. if (!pond.hasOwnProperty(type)) pond[type] = [];
    7. let arr = pond[type];
    8. if (arr.includes(func)) return; //去重
    9. arr.push(func);
    10. };
    11. // 从事件池中移除订阅
    12. const off = function off(type, func) {
    13. let arr = pond[type] || [];
    14. if (arr.length === 0) return;
    15. let i = 0,
    16. item;
    17. for (; i < arr.length; i++) {
    18. item = arr[i];
    19. if (item === func) {
    20. // arr.splice(i, 1); //引发数组塌陷
    21. arr[i] = null;
    22. return;
    23. }
    24. }
    25. };
    26. // 通知事件池中,指定类型的方法去执行
    27. const fire = function fire(type, ...params) {
    28. let arr = pond[type] || [],
    29. i = 0,
    30. item;
    31. for (; i < arr.length; i++) {
    32. item = arr[i];
    33. if (typeof item === 'function') {
    34. item(...params);
    35. continue;
    36. }
    37. // 当期这一项不是函数,则我们把其移除掉
    38. arr.splice(i, 1);
    39. i--;
    40. }
    41. };
    42. /* 暴露API */
    43. let sub = {
    44. on,
    45. off,
    46. fire
    47. };
    48. if (typeof window !== 'undefined') window.sub = sub;
    49. //node环境
    50. if (typeof module === 'object' && typeof module.exports === 'object') module.exports = sub;
    51. })();

    使用方案如下:

    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);