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

手写一个发布-订阅模式 #110

Open
sisterAn opened this issue Sep 21, 2020 · 3 comments
Open

手写一个发布-订阅模式 #110

sisterAn opened this issue Sep 21, 2020 · 3 comments

Comments

@sisterAn
Copy link
Owner

sisterAn commented Sep 21, 2020

class EventEmitter {
  constructor() {
    // 初始值为空对象
    this.listeners = Object.create(null)
  }
  
  // 注册事件
  on = (event, listener) => {
    // this.bindEvent(event, listener, false)
    if (!event || !listener) {
      return
    }
    if (this.listeners[event]) {
        //如果有就放一个新的
        this.listeners[event].push(listener)
    } else {
        //如果没有就创建一个数组
        this.listeners[event] = [listener]
    }
  }
  
  // 只订阅一次
  once = (event, listener) => {
    // this.bindEvent(event, listener, true)
    function one() {
        // 在one函数运行原来的函数,只有将one清空
        listener.apply(this, arguments)
        // 先绑定 执行后再删除
        this.off(event)
    }
      this.on(event, one)
      //此时emit触发会执行此函数,会给这个函数传递rest参数
  }
  
  // 发布事件
  emit = (event, ...args) => {
    if (!this.hasBind(event)) {
      console.warn(`this event: ${event} don't has bind listener.`)
      return
    }

    this.listeners[event].forEach(listener => listener.call(this, ...args))
  }
  
  // 取消订阅
  off = (event, listener) => {
    if (!this.hasBind(event)) {
      console.warn(`this event: ${event} don't exist.`)
      return
    }

    // remove all listener
    if (!listener) {
      delete this.listeners[event]
      return
    }

    // remove specific listener
    this.listeners[event] = this.listeners[event].filter(item => item !== listener)
  }

  hasBind = event => {
    return this.listeners[event]
      && this.listeners[event].length
  }
}

// 测试
const baseEvent = new EventEmitter()
function cb(value){
    console.log("hello "+value)
}
baseEvent.once("click",cb)
// baseEvent.off("click")
baseEvent.emit("click",'2020')
// hello 2020
console.log(baseEvent.listeners)
@chenguzhen87
Copy link

因该要加一个逻辑,不然该事件清除了,又调用解绑事件
if (this.listeners[event]) {
this.off(event)
}

@omitchen
Copy link

omitchen commented Dec 9, 2020

this.off(event)

执行一次把前面所有订阅的事件都卸载了,不太合适吧

@xllpiupiu
Copy link

/**
 * https://blog.csdn.net/weixin_43792004/article/details/113442506
 */
//中间人 主题
class Dep {
    constructor(callback) {
        this.subs = []
        this.callback = callback
    }
    addSub(sub) {
        this.subs.push(sub)
        return this
    }
    notify() {
        this.subs.forEach(item=>item.update(this.callback))
    }
}
//订阅者
class Sub {
    constructor(val) {
        this.val = val
    }
    update(callback) {
        this.val = callback(this.val);
        console.log('this.val: ', this.val);
    }
}
//发布者
class Pub {
    constructor() {
        this.deps = []
    }
    addDep(dep) {
        this.deps.push(dep)
    }
    removeDep(dep) {
        let index = this.deps.indexOf(dep)
        if(index!==-1) {
            this.deps.splice(index,1)
            return true
        }
        return false
    }
    publish(dep) {
        this.deps.forEach(item=>item===dep&&item.notify())
    }
}
let dep1 = new Dep(item=>item*item)
let sub1 = new Sub(3)
dep1.addSub(sub1)
let pub1 = new Pub()
pub1.addDep(dep1)
pub1.publish(dep1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants