Sunny-117 / js-challenges

✨✨✨ Challenge your JavaScript programming limits step by step

Home Page:https://juejin.cn/column/7244788137410560055

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

发布订阅者模式

Sunny-117 opened this issue · comments

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))
  }
}
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

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
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)
	}
}
commented
// 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
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("事件一");

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];
          }
        }
      }
    }
  }
}
commented
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);
    }
}
commented

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
);
}
}

commented

// 定义事件类
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);
}
}
}
}