Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

手写题:事件总线 #10

Open
Hongbusi opened this issue Jun 9, 2022 · 4 comments
Open

手写题:事件总线 #10

Hongbusi opened this issue Jun 9, 2022 · 4 comments

Comments

@Hongbusi
Copy link
Member

Hongbusi commented Jun 9, 2022

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
  }
}
@betteroneday
Copy link

betteroneday commented Jun 9, 2022

image

看起来index这行代码似乎并不需要,index和i是一致的。

handlers.splice(i, 1)

@Hongbusi Hongbusi added the today 每日一题。 label Jun 10, 2022
@Hongbusi
Copy link
Member Author

Hongbusi commented Jun 10, 2022

使用 splice 删除 handlers 一个元素之后,其他元素的下标可能会发生改变。@betteroneday

const arr = [1, 2, 3, 4]

// 假设有一个 for 循环
arr.splice(i, 1) // i = 0, 此时 arr = [2, 3, 4]
arr.splice(i, 1) // i = 1, 此时 arr = [2, 4]
...

@baboon-king
Copy link

mini 版来了

class EventEmitter {
  constructor() {
    this.subs = Object.create(null);
  }

  $on(eventType, handler) {
    this.subs[eventType] = this.subs[eventType] || [];
    this.subs[eventType].push(handler);
  }

  $emit(eventType, ...params) {
    this.subs[eventType].forEach((handler) => handler(...params));
  }
}
const em = new EventEmitter();

function handleClick(params1) {
  console.log("clicked", params1);
}

em.$on("click", handleClick);

em.$on("click", (params1) => {
  console.log("clicked2", params1);
});

em.$on("change", (params1, params2) => {
  console.log(`changed:通过${params1},改变成${params2}`);
});

@Hongbusi Hongbusi changed the title 手写事件总线 手写题:事件总线 Jun 10, 2022
@lyx-jay
Copy link

lyx-jay commented Jun 10, 2022

简单版 EventBus

class EventBUs {
  constructor() {
    this.cache = {};
  }

  on(name, cb) {
    if (this.cache[name]) {
      this.cache[name].push(cb);
    } else {
      this.cache[name] = [cb];
    }
  }

  off(name, cb) {
    let callbacks = this.cache[name];
    if (callbacks) {
      const index = callbacks.findIndex(f => f === cb);
      if (index >= 0) {
        callbacks.splice(index, 1);
      }
    }
  }

  emit(name, once=false, ...args) {
    if (this.cache[name]) {
      let callbacks = this.cache[name].slice();
      for (let cb of callbacks) {
        cb(...args);
      }
      if (once) {
        delete this.cache[name];
      }
    }
  }
}

@Hongbusi Hongbusi removed the today 每日一题。 label Jun 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants