Skip to content

手写题:事件总线 #10

Open
Open
@Hongbusi

Description

@Hongbusi
class EventBus {
  constructor() {
    this.eventBus = {}
  }

  on(eventName, eventCallback, thisArg) {
    if (typeof eventName !== 'string') {
      throw new TypeError('the event name must be string type')
    }

    if (typeof eventCallback !== 'function') {
      throw new TypeError('the event callback must be function type')
    }

    let handlers = this.eventBus[eventName]
    if (!handlers) {
      handlers = []
      this.eventBus[eventName] = handlers
    }

    handlers.push({
      eventCallback,
      thisArg
    })

    return this
  }

  off(eventName, eventCallback) {
    if (typeof eventName !== 'string') {
      throw new TypeError('the event name must be string type')
    }

    if (typeof eventCallback !== 'function') {
      throw new TypeError('the event callback must be function type')
    }

    const handlers = this.eventBus[eventName]
    if (handlers && eventCallback) {
      const newHandlers = [...handlers]
      for (let i = 0; i < newHandlers.length; i++) {
        const handler = newHandlers[i]
        if (handler.eventCallback === eventCallback) {
          const index = handlers.indexOf(handler)
          handlers.splice(index, 1)
        }
      }
    }

    if (handlers.length === 0) {
      delete this.eventBus[eventName]
    }
  }

  once(eventName, eventCallback, thisArg) {
    if (typeof eventName !== 'string') {
      throw new TypeError('the event name must be string type')
    }

    if (typeof eventCallback !== 'function') {
      throw new TypeError('the event callback must be function type')
    }

    const tempCallback = (...payload) => {
      this.off(eventName, tempCallback)
      eventCallback.apply(thisArg, payload)
    }

    return this.on(eventName, tempCallback, thisArg)
  }

  emit(eventName, ...payload) {
    if (typeof eventName !== 'string') {
      throw new TypeError('the event name must be string type')
    }

    const handlers = this.eventBus[eventName] || []
    handlers.forEach((handler) => {
      handler.eventCallback.apply(handler.thisArg, payload)
    })
    return this
  }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions