发布订阅(观察者)模式

读书笔记

曾探. JavaScript设计模式与开发实践 (图灵原创). 人民邮电出版社. Kindle 版本.


它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在JavaScript开发中,我们一般用事件模型来替代传统的发布—订阅模式。

var Event = (function () {
  var global = this,
      Event,
      _default = 'default';

  Event = function () {
    var _listen,
        _trigger,
        _remove,
        _slice = Array.prototype.slice,
        _shift = Array.prototype.shift,
        _unshift = Array.prototype.unshift,
        namespaceCache = {},
        _create,
        find,
        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 (vari = 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, 
          ret, 
          stack = cache[key]; 

      if (!stack || !stack.length) { 
        return; 
      } 

      return each(stack, function () { 
          returnthis.apply(_self, args); 
      }); 
    }; 

    _create = function (namespace) {
      var namespace = namespace || _default; 
          varcache = {},
          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;

})();

results matching ""

    No results matching ""