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

发布订阅者模式 #60

Open
Sunny-117 opened this issue Nov 3, 2022 · 9 comments
Open

发布订阅者模式 #60

Sunny-117 opened this issue Nov 3, 2022 · 9 comments

Comments

@Sunny-117
Copy link
Owner

class EventEmitter {
  constructor() {
    // key: 事件名
    // value: callback [] 回调数组
    this.events = {}
  }
  on(name, callback) {
    if (this.events[name]) {
      this.events[name].push(callback)
    } else {
      this.events[name] = [callback]
    }
  }
  off(name, callback) {
    if (!this.message[name]) return;
    if (!callback) {
      // 如果没有callback,就删掉整个事件
      this.message[name] = undefined;
    }
    this.message[name] = this.message[name].filter((item) => item !== callback);

  }
  emit(name, ...args) {
    if (!this.events[name]) return
    this.events[name].forEach(cb => cb(...args))
  }
}
@lxy-Jason
Copy link
Contributor

class EventEmitter {
  constructor() {
    // key: 事件名
    // value: callback [] 回调数组
    this.events = {}
  }
  on(name, callback) {
    if (this.events[name]) {
      this.events[name].push(callback)
    } else {
      this.events[name] = [callback]
    }
  }
  off(name, callback) {
    if (!this.message[name]) return;
    if (!callback) {
      // 如果没有callback,就删掉整个事件
      this.message[name] = undefined;
    }
    this.message[name] = this.message[name].filter((item) => item !== callback);

  }
  emit(name, ...args) {
    if (!this.events[name]) return
    this.events[name].forEach(cb => cb(...args))
  }
}

是不是写串了?没有声明this.message

@lxy-Jason
Copy link
Contributor

class EventEmiter {
  constructor() {
    this.cache = {}; //存放不同的事件
  }
  on(name,fn){ //事件名,回调
    if(this.cache[name]){
      this.cache[name].push(fn)
    }
    else{
      this.cache[name] = [fn]; //添加新事件
    }
  }
  off(name,fn){ //删除事件的某个回调
    let tasks = this.cache[name]; //拿到对应的回调队列
    if(tasks){
      const index = tasks.findIndex(f => f === fn);
      if(index >= 0){
        tasks.splice(index,1)
      }
    }
  }
  emit(name,once = false,...args){
    if(this.cache[name]){
      //创建副本,如果回调函数内继续注册相同事件会造成死循环
      let tasks = this.cache[name].slice();
      for(let fn of tasks){
        fn(...args)
      }
      if(once){
        delete this.cache[name]
      }
    }
  }
}
//test
let eventsBus = new EventEmiter()
let fn1 = function(name,age){
  console.log(name,age)
}
let fn2 = function(name,age){
  console.log('fn',name,age);
}
eventsBus.on("test",fn1)
eventsBus.on("test",fn2)
eventsBus.emit("test",false,"Jason",18)
//Jason 18
//fn Jason 18

@veneno-o
Copy link
Contributor

class EventEmitter {
	cache = new Map();
	$on(eventName, cb) {
		this.cache.has(eventName)
			? this.cache.get(eventName).push(cb)
			: this.cache.set(eventName,[cb]);
	}

	$off(eventName) {
		this.cache.delete(eventName);
	}

	$emit(eventName) {
		if (!this.cache.has(eventName)) {
			return;
		}
		for (const cb of this.cache.get(eventName)) {
			cb();
		}
		this.$off(eventName)
	}
}

@zhuba-Ahhh
Copy link
Contributor

// 1- on和once 注册并存储函数
// 2- emit 找到并执行相应的函数
// 3- off 找到并删除相应的函数
// 4- on和once on绑定的事件可以多次执行,除非off; once绑定的函数emit一次即删除,也可以未执行而被off;所以需要在数据结构中标明on、once
// 5- 事件是有序的,有执行先后顺序

class EventBus {
  private events: {
    [key: string]: Array<{ fn: Function; isOnce: boolean }>;
  };

  constructor() {
    this.events = {};
  }

  /**
   *
   * on 绑定函数可多次触发
   * @param {string} type
   * @param {Function} fn
   * @param {boolean} [isOnce=false]
   * @memberof EventBus
   */
  on(type: string, fn: Function, isOnce: boolean = false) {
    const events = this.events;
    if (events[type] == null) events[type] = []; // 初始化 key 的 fn数组

    events[type].push({ fn, isOnce });
  }

  /**
   *
   * 绑定函数,并只会执行一次
   * @param {string} type
   * @param {Function} fn
   * @memberof EventBus
   */
  once(type: string, fn: Function) {
    this.on(type, fn, true); // 复用逻辑
  }

  /**
   *
   * 解绑事件
   * @param {string} type
   * @param {Function} [fn]
   * @memberof EventBus
   */
  off(type: string, fn?: Function) {
    if (!fn) {
      // 若果fn没有值,就解绑所有 type 的函数
      this.events[type] = [];
    } else {
      // 解绑单个fn
      const typeFnList = this.events[type];
      if (typeFnList) {
        this.events[type] = typeFnList.filter((typeFn) => typeFn.fn !== fn);
      }
    }
  }

  emit(type: string, ...args: any[]) {
    const typeFnList = this.events[type];
    if (typeFnList == null) return;

    this.events[type] = typeFnList.filter((typeFn) => {
      const { fn, isOnce } = typeFn;
      fn(...args);

      // once 执行一次就被过滤掉
      if (!isOnce) return true;
      else return false;
    });
  }
}

const e = new EventBus();

function fn1(a: any, b: any) {
  console.log("fn1", a, b);
}
function fn2(a: any, b: any) {
  console.log("fn2", a, b);
}
function fn3(a: any, b: any) {
  console.log("fn3", a, b);
}

e.on("key1", fn1);
e.on("key1", fn2);
e.once("key1", fn3); // 只会被触发一次
e.on("key2", fn3);

e.emit("key1", 10, 20); // 触发 fn1、fn2、fn3
e.emit("key1", 11, 22); // 触发 fn1、fn2

e.off("key1", fn1); // 解绑 fn1

e.emit("key1", 100, 200); // 触发 fn2

split-on-once

class EventBus {
  private events: { [key: string]: Array<Function> };
  private onceEvent: { [key: string]: Array<Function> };

  constructor() {
    this.events = {};
    this.onceEvent = {};
  }

  /**
   *
   * on 绑定函数可多次触发
   * @param {string} type
   * @param {Function} fn
   * @param {boolean} [isOnce=false]
   * @memberof EventBus
   */
  on(type: string, fn: Function) {
    const events = this.events;
    if (events[type] == null) events[type] = []; // 初始化 key 的 fn数组

    events[type].push(fn);
  }

  /**
   *
   * 绑定函数,并只会执行一次
   * @param {string} type
   * @param {Function} fn
   * @memberof EventBus
   */
  once(type: string, fn: Function) {
    const onceEvent = this.onceEvent;
    if (onceEvent[type] == null) onceEvent[type] = []; // 初始化 key 的 fn数组

    onceEvent[type].push(fn);
  }

  /**
   *
   * 解绑事件
   * @param {string} type
   * @param {Function} [fn]
   * @memberof EventBus
   */
  off(type: string, fn?: Function) {
    if (!fn) {
      // 若果fn没有值,就解绑所有 type 的函数
      this.events[type] = [];
      this.onceEvent[type] = [];
    } else {
      // 解绑单个fn
      const typeFnList = this.events[type];
      // const onceTypeFnList = this.onceEvent[type];
      if (typeFnList) {
        this.events[type] = typeFnList.filter((typeFn) => typeFn !== fn);
      }

      // if (typeFnList) {
      //   this.events[type] = onceTypeFnList.filter(
      //     (onceTypeFn) => onceTypeFn !== fn
      //   );
      // }
    }
  }

  emit(type: string, ...args: any[]) {
    const typeFnList = this.events[type];
    const onceTypeFnList = this.onceEvent[type];

    if (typeFnList) {
      typeFnList.forEach((typeFn) => {
        typeFn(...args);
      });
    }

    if (onceTypeFnList) {
      onceTypeFnList.forEach((onceTypeFn) => {
        onceTypeFn(...args);

        // once执行一次就删除
        this.onceEvent[type] = [];
      });
    }
  }
}

const e = new EventBus();

function fn1(a: any, b: any) {
  console.log("fn1", a, b);
}
function fn2(a: any, b: any) {
  console.log("fn2", a, b);
}
function fn3(a: any, b: any) {
  console.log("fn3", a, b);
}

e.on("key1", fn1);
e.on("key1", fn2);
e.once("key1", fn3); // 只会被触发一次
e.on("key2", fn3);

e.emit("key1", 10, 20); // 触发 fn1、fn2、fn3
e.emit("key1", 11, 22); // 触发 fn1、fn2

e.off("key1", fn1); // 解绑 fn1

e.emit("key1", 100, 200); // 触发 fn2

@LittlebearHat
Copy link
Contributor

let obj = {}; //保存的内容
function on(id, f) {
  if (!obj[id]) {
    obj[id] = [];
  }
  obj[id].push(f); //注册事件
}
function emit(id, msg) {
  if (!obj[id]) return;
  obj[id].forEach((f) => f(msg)); //一对多执行
}
function off(id, f) {
  if (!obj[id]) return; //没有注册则跳出
  if (!f) {
    //如果没指定删除事件则解绑所有函数
    obj[id] = [];
  }
  obj[id] = obj[id].filter((f1) => f1 !== f);
}
const f1 = (msg) => console.log("触发1", msg);
const f2 = (msg) => console.log("触发2", msg);
on("事件一", f1);
on("事件一", f2);
emit("事件一", 6);
off("事件一", f1);
emit("事件一", 6);
off("事件一");
emit("事件一");

@kangkang123269
Copy link

class EventEmitter {
  constructor() {
    this.events = {};
  }

  on(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }

  once(eventName, callback) {
    const onceCallback = (...args) => {
      callback.apply(this, args);
      this.off(eventName, onceCallback);
    };
    this.on(eventName, onceCallback);
  }

  emit(eventName, ...args) {
    const callbacks = this.events[eventName];
    if (callbacks) {
      callbacks.forEach((callback) => {
        callback.apply(this, args);
      });
    }
  }

  off(eventName, callback) {
    const callbacks = this.events[eventName];
    if (callbacks) {
      if (!callback) {
        delete this.events[eventName];
      } else {
        const index = callbacks.indexOf(callback);
        if (index !== -1) {
          callbacks.splice(index, 1);
          if (callbacks.length === 0) {
            delete this.events[eventName];
          }
        }
      }
    }
  }
}

@bearki99
Copy link

bearki99 commented Mar 8, 2023

class EventEmitter{
    constructor(){
        this.event = {};
    }
    on(name, callback){
        if(this.event[name]){
            this.event[name].push(callback);
        }else{
            this.event[name] = [callback];
        }
    }
    off(name, callback){
        if(!this.event[name]) return;
        if(!callback) this.event[name] = [];
        this.event[name] = this.event[name].filter((item)=>{
            item !== callback && item.initialCallback !== callback;
        })
    }
    emit(name, ...callbacks){
        if(!this.event[name]) return;
        this.event[name].forEach((cb)=>cb(...callbacks));
    }
    once(name, callback){
        const one = (...args) => {
            callback(...args);
            this.off(name, one);
        }
        one.initialCallback = callback;
        this.on(name, one);
    }
}

@cscty
Copy link

cscty commented Jun 17, 2023

class Event {
constructor() {
// key为事件名,value为事件数组
this.events = {};
}
on(key, fn) {
if (this.events[key]) this.events[key].push(fn);
else this.events[key] = [fn];
}
emit(key, ...args) {
if (!this.events[key]) return;
this.events[key].forEach((fn) => fn(...args));
}
off(key, fn) {
if (!this.events[key]) return;
if (!fn) this.events[key] = undefined;
else
this.events[key] = this.events[key].filters(
(val) => val !== fn
);
}
}

@flawlessv
Copy link

// 定义事件类
class Event {
private handlers: { [key: string]: Function[] } = {};

// 添加事件监听器
public on(eventName: string, handler: Function): void {
if (!this.handlers[eventName]) {
this.handlers[eventName] = [];
}
this.handlers[eventName].push(handler);
}

// 触发事件
public emit(eventName: string, data?: any): void {
const handlers = this.handlers[eventName];
if (handlers) {
handlers.forEach(handler => {
handler(data);
});
}
}

// 移除事件监听器
public off(eventName: string, handler: Function): void {
const handlers = this.handlers[eventName];
if (handlers) {
const index = handlers.indexOf(handler);
if (index !== -1) {
handlers.splice(index, 1);
}
}
}
}

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

No branches or pull requests

9 participants