Skip to content
On this page

一个发布订阅模式实现

js
/**
 * 发布订阅模式
 */

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

  /**
   * 需要有  listen trigger remove create
   */
  return (function () {
    // 定义模式
    var _listen, _trigger, _remove, _create;
    // 定义方法
    var _shift = Array.prototype.shift, _unshift = Array.prototype.unshift, _slice = Array.prototype.slice;
    var each = function (arr, fn) {
      var ret;
      for (var index = 0; index < arr.length; index++) {
        var item = arr[index];
        ret = fn.call(item, index, item);
      }
      return ret;
    }
    // 定义空间
    var namespaceCache = {};

    _listen = function (cache, key, fn) {
      if (!cache[key]) {
        cache[key] = [];
      }
      cache[key].push(fn);
    }

    _trigger = function () {
      var cache = _shift.call(arguments),
        key = _shift.call(arguments),
        args = arguments,
        stack = cache[key],
        _self = this;

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

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

    _remove = function (cache, key, fn) {
      if (cache[key]) {
        cache[key].forEach(function (item, index) {
          if (item === fn) {
            cache[key].splice(index, 1);
          }
        });
      } else {
        cache[key] = [];
      }
    }

    _create = function (namespace) {
      var namespace = namespace || _default;
      var cache = {},
        offlineStack = []; // 离线时间
      var ret = {
        listen: function (key, fn, last) {
          _listen(cache, key, fn);
          // 如果离线时间栈是null,则之间听,否则需要将事件放入离线栈
          if (offlineStack === null) {
            return;
          }
          // 表明执行最后一个事件
          if (last === 'last') {
            offlineStack.length && offlineStack.pop()();
          } else {
            each(offlineStack, function () {
              return this();
            })
          }

          offlineStack = null;
        },
        one: function (key, fn, last) {
          this.remove(key, fn);
          this.listen(key, fn, last);
        },
        remove: function (key, fn) {
          _remove(cache, key, fn);
        },
        trigger: function () {
          var fn, args, _self = this;
          // 将cache放入首位
          _unshift.call(arguments, cache);
          args = arguments;
          fn = function () {
            return _trigger.apply(_self, args);
          };
          // 如果有离线事件,则放进去
          if (offlineStack) {
            return offlineStack.push(fn);
          }
          return fn();
        }
      }

      return namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = 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);
      }
    }
  }())

}())


Event.trigger('click', 1);
Event.listen('click', function (a) {
  console.log(a);
})


Event.create('name').listen('click', function (a) {
  console.log('name', a);
})
Event.create('name').trigger('click', 1);


Event.create('name2').trigger('click', 1);
setTimeout(function () {
  Event.create('name2').listen('click', function (a) {
    console.log('name2', a);
  })
}, 1000);