前言
上一节已经大致描述了一个传统的简单事件总线模块的设计,以及 bpmn.js 中的事件总线 EventBus 所新增的功能,以及他的订阅者的存储方式。那么这一节我们就从源码层面来理解整个事件总线模块的实现方式。
1. 实例方法
bpmn.js 的 EventBus 模块,默认提供订阅注册(on, once)、订阅取消(off)、事件/消息发布(fire)、错误处理(handleError),以及标准事件/消息体创建方法(createEvent)。
其中订阅注册方法 on 和 once,都接收4个参数:events 事件名(可复数)、priority 权重、callback 回调函数、that 上下文。
其中 events 和 callback 肯定是必传参数,用来注册某个事件类型的订阅,以及需要执行的函数;权重不传则默认是 1000.
另外还有一系列的私有方法,例如订阅函数的执行方法 _invokeListener
和 _invokeListeners
,销毁方法 _destroy
等。
2. 订阅注册
2.1 on 和 once
之前说过,订阅注册的两个方法 on 和 once 的区别主要在于,once 注册的订阅者在执行了一次之后就会取消订阅,但在之前的注册过程则基本一致。
var FN_REF = '__fn';
var DEFAULT_PRIORITY = 1000;
var slice = Array.prototype.slice;
export default function EventBus() {this._listeners = {};
}
EventBus.prototype.on = function(events, priority, callback, that) {events = isArray(events) ? events : [ events ];if (isFunction(priority)) {that = callback;callback = priority;priority = DEFAULT_PRIORITY;}if (!isNumber(priority)) {throw new Error('priority must be a number');}var actualCallback = callback;if (that) {actualCallback = bind(callback, that);actualCallback[FN_REF] = callback[FN_REF] || callback;}var self = this;events.forEach(function(e) {self._addListener(e, {priority: priority,callback: actualCallback,next: null});});
};
EventBus.prototype.once = function(event, priority, callback, that) {var self = this;if (isFunction(priority)) {that = callback;callback = priority;priority = DEFAULT_PRIORITY;}if (!isNumber(priority)) {throw new Error('priority must be a number');}function wrappedCallback() {wrappedCallback.__isTomb = true;v