blob: 5ec1dd5d8ad34ba5c7c9770f30d3d39e701b988c [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import utils from './utils'
import * as DEBUG from 'debug'
const debug = DEBUG('emitter')
export default class Emitter {
private eventHandler: any = {}
on(event: any, namespace: string, handler: any) {
if (arguments.length === 2) {
handler = namespace
namespace = ''
}
if (!this.eventHandler[event]) {
this.eventHandler[event] = {}
}
const target = utils.locateEventHanlderByNamespace(this.eventHandler[event], namespace)
if (target.__handlers__) {
target.__handlers__.push(handler)
} else {
target.__handlers__ = [handler]
}
}
off(event: string, namespace: string) {
if (this.eventHandler[event]) {
if (!namespace) {
this.eventHandler[event] = {}
} else {
utils.clearEventHandlerByNamespace(this.eventHandler[event], namespace)
}
}
}
emit(event: string | number, namespace: string, data: any) {
if (arguments.length === 2) {
data = namespace
namespace = ''
}
if (this.eventHandler[event]) {
const context = {
namespace,
event,
path: namespace,
}
return this._emit(this.eventHandler[event], namespace, context, data)
} else {
return false
}
}
private _emit(prevTarget: any, namespace: string, context: any, data: any) {
context.path = namespace
const target = utils.getEventHanlderByNamespace(prevTarget, namespace)
if (target && target.__handlers__) {
target.__handlers__.forEach(h => h.call(context, data))
} else {
if (namespace) {
const ns = namespace.substr(0, namespace.lastIndexOf('.'))
return this._emit(prevTarget, ns, context, data)
} else {
return false
}
}
}
broadcast(event: any, namespace: string, data: any) {
debug(`broadcast ${event}, ${namespace}, ${data}`)
if (arguments.length === 2) {
data = namespace
namespace = ''
}
if (this.eventHandler[event]) {
const target = utils.getEventHanlderByNamespace(this.eventHandler[event], namespace)
if (target) {
const context = { event, namespace, path: namespace }
this._broadcast(target, context, data)
return true
} else {
return false
}
} else {
return false
}
}
private _broadcast(target: any, context: any, data: any) {
target.__handlers__ && target.__handlers__.forEach(h => h.call(context, data))
const keys = Object.keys(target).filter(k => k !== '__handlers__')
keys.forEach(k => {
const ctx = {
event: context.event,
namespace: context.namespace,
path: context.namespace + '.' + k,
}
this._broadcast(target[k], ctx, data)
})
}
}