JS观察者模式

本文介绍了一种实用的事件驱动设计模式,适用于自定义事件、复杂回调嵌套及跨模块触发场景,通过代码实例展示了模式的实现方式及其优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用场景:
1、需要自定义事件的时候可以使用模式
2、当回调嵌套特别复杂时,可以考虑使用该模式
3、当某一操作触发,同时会改变其它模块(比如IM消息到达),可以使用该模式
优点:
代码解耦,模块独立
缺点:
过度使用的话,会导致模块间关系混乱,代码不好维护
var Event = (function() {
    var _event,
        _default = 'default';

    _event = function() {
        var _listen,
            _trigger,
            _remove,
            _shift = Array.prototype.shift,
            _unshift = Array.prototype.unshift,
            namespaceCache = {},
            _create,
            each = function( ary, fn) {  //循环
                var ret;
                for(var i = 0, l = ary.length; i < l; i++) {
                    var n = ary[i];
                    ret = fn.call(n, i, n);
                }
                return ret;
            };
        // 订阅
        _listen = function(key, fn, cache) {
            if(!cache[key]) {
                cache[key] = [];
            }
            cache[key].push(fn);
        };
        // 移除订阅
        _remove = function(key, cache, fn) {
            if(cache[key]) {
                if(fn) {
                    for(var i = cache[key].length; i >=0; i++) {
                        if(cache[key][i] === fn) {
                            cache[key].splice(i, 1);
                        }
                    }
                }else {
                    cache[key] = [];
                }
            }
        };
        // 发布
        _trigger = function() {
            var cache = _shift.call(arguments),
                key = _shift.call(arguments),
                args = arguments,
                _self = this,
                stack = cache[key];
            if(!stack || !stack.length) {
                return;
            }
            return each(stack, function() {
                return this.apply(_self, args);
            });
        };
        // 创建命名空间(同一事件名可能不同处理,比如同时多个IM)
        _create = function(namespace) {
            var namespace = namespace || _default;
            var cache = {},
                offlineStack = [],  // 离线事件
                ret = {
                    listen: function (key, fn, last) {
                        _listen(key, fn, cache);
                        if (offlineStack == null) {
                            return;
                        }
                        if (last === 'last') {
                            offlineStack.length && offlineStack.pop()();
                        } else {
                            each(offlineStack, function () {
                                this();
                            });
                        }
                        offlineStack = null;
                    },
                    one: function (key, fn, last) {
                        _remove(key, cache);
                        this.listen(key, fn, last);
                    },
                    remove: function(key, fn) {
                        _remove(key, cache, fn);
                    },
                    trigger: function() {
                        var fn,
                            args,
                            _self = this;
                        _unshift.call(arguments, cache);
                        args = arguments;
                        fn = function() {
                            return _trigger.apply(_self, args);
                        };
                        if(offlineStack) {
                            return offlineStack.push(fn);
                        }
                        return fn();
                    }
                };
            return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;
        };

        return {
            create: _create,
            one: function(key, fn, last) {
                var event = this.create();
                event.one(key, fn, last);
            },
            remove: function(key, fn) {
                var event = this.create();
                event.remove(key, fn);
            },
            listen: function(key, fn, last) {
                var event = this.create();
                event.listen(key, fn, last);
            },
            trigger: function() {
                var event = this.create();
                event.trigger.apply(this, arguments);
            }
        };
    }();
    return _event;
})();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值