发布-订阅模式实现【js设计模式】

代码实现

// event.js
var Event = (function() {
    var _callbacks = {}, listen, emit, remove; //_callbacks 缓存所有订阅者的回调函数
    listen = function(eventName, fn) {
        if(!_callbacks[eventName]) {
            _callbacks[eventName] =[fn];
        } else{
            _callbacks[eventName].push(fn);
        }
    };
    //写法一,要求传入两个参数
    // emit = function(eventName,argus) {
    //     var fns = _callbacks[eventName]
    //     if(!fns || fns.length === 0) {
    //         return false;
    //     }
    //     var args = {
    //         eventName: eventName,
    //         argus: argus,
    //         eventDate: new Date() //可以添加每次事件触发时间
    //     }
    //     for(let i=0;i<fns.length;i++){
    //         fns[i].call(this,args)
    //     }
    // }
    //写法二,可以追加随意数量参数
    emit = function() {
        var eventName = Array.prototype.shift.call(arguments),fns = _callbacks[eventName];
        if(!fns || fns.length === 0) {
            return false;
        }
        for(let i=0;i<fns.length;i++){
            fns[i].apply(this,arguments)
        }
    };
    remove = function(eventName, fn){
        var fns = _callbacks[eventName];
        if(fns.length!==0) {
            for(let i=fns.length-1;i>=0;i--){
                var _fn = fns[i];
                if(_fn === fn) {
                    fns.splice(i,1);
                }
            }
        }
    };
    return {
        listen: listen,
        emit:emit,
        remove:remove
    }

})();
/** index.jsx */
<body>
    <button id='count'>点击</button>
    <div id='showCount'></div>
    <script src='./event.js'></script>
    <script>
        //发布
        var a=(function(){
            var count =0;
            var button = document.getElementById('count');
            button.onclick=function(){
                Event.emit('add', count++)
            }
        })();
        //订阅
        var b=(function(){
            var div=document.getElementById('showCount');
            Event.listen('add',function(count){
                div.innerHTML = count;
            })
        })()
    </script>
</body>

含义说明

又称观察者模式,一对多关系,发布者状态改变时,所有相关事件订阅者收到通知,触发相应回调。

应用

1.组件间传递数据、框架间跨组件传递数据。
2.异步编程中,替代回调函数,可以订阅ajax之后的事件,只要订阅自己需要的部分。
3.对象之间的松耦合。同一发布者的内部代码改变,只要约定的事件名称没有改变,不影响订阅;新增订阅者不影响其他订阅者。

不足

1.但使用过度,代码不好理解和维护。
2.无法知道消息传送是成功的还是失败的,信道不会通知系统消息传送的状态。


介绍下观察者模式和订阅-发布模式的区别,各自适用于什么场景

观察者模式中主体和观察者是互相感知的,发布-订阅模式是借助第三方来实现调度的,发布者和订阅者之间互不感知
发布-订阅模式就好像报社, 邮局和个人的关系,报纸的订阅和分发是由邮局来完成的。报社只负责将报纸发送给邮局。
观察者模式就好像 个体奶农和个人的关系。奶农负责统计有多少人订了产品,所以个人都会有一个相同拿牛奶的方法。奶农有新奶了就负责调用这个方法。

https://juejin.cn/post/6844903513009422343

引申

当多处同时出发事件,作用于同一作用域,应该怎么控制程序不出错?

我的两个思路:
1.设定开关变量(flag)监测是否正在执行某操作,等开关打开,其他事件才可执行;
2.队列(queue)形式,维护回调函数,批量处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咩咩羊10

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值