node --- > 模拟事件的异步

事件

  • 在前端浏览器最常见的就是页面交互事件
  • 本质是发布/订阅设计模式

目标

  • 对象使用add方法订阅事件。
  • 使用emit发布消息

订阅事件

  • 添加触发事件的一个唯一字符串,以及对应的处理函数
  • 先初始化事件对象
class Event {
	constructor(){
		this.events = {};
	}
}
  • 订阅
  • 在订阅事件的时候,需要先判断事件是否存在.
  • 若不存在,则直接加入到队列(数组)
  • 若存在,则放到队尾(push进入)
class Event {
	constructor(){...},
	add(name, cb) {
		if (this.map[name]) {
			this.map[name].push(fn);
			return;
		}
		this.map[name] = [fn];
		return;
	}
}

发布事件

  • 当使用emit方法是,传入的第一个参数是事件的名称.
  • emit方法会根据传入的名称,找到对应的事件处理组.
  • 利用事件处理组对后面的参数进行依次调用
class Event {
	constructor(){ ... }
	emit(name, ...args) {
		this.map[name].forEach( cb => {
			cb(...args);
		})
	}
}

调用

const e = new Event();
e.add('sayHello', (err, name) =>{
	if(err) {
		console.error(err);
		return
	}
	console.log(`hello ${name}`);
	return
})
e.emit('sayHello','发生了错误');
e.emit('sayHello', null, 'marron');

在这里插入图片描述


链式调用的实现

  • 想使用如下的方式进行调用
const e = new Event();
e
.add('sayHello', (err, name) =>{
	if(err) {
		console.error(err);
		return;
	}
	console.log(`hello ${name}`);
})
.emit('sayHello', '发生了错误')
.emit('sayHello', null, 'mar~!');
  • 只需保证调用add后的执行还是当前的实例(e)即可
  • 在类Event的内部,this指向的是当前的实例,因此只需在add方法中返回this即可实现
  • 改写Event,注意return 语句
class Event {
    constructor() {
        this.events = {};
    }
    add(name, cb) {
        if (this.events[name]) {
            this.events[name].push(cb);
            return this; // 返回当前实例
        }
        this.events[name] = [cb];
        return this;
    }
    emit(name, ...args) {
        if (this.events[name]) {
            this.events[name].forEach(cb => {
                cb(...args);
            })
            return this;
        } else {
            console.error('[Event Error]: 该事件未注册')
        }
    }
}

在这里插入图片描述

发布了177 篇原创文章 · 获赞 22 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/piano9425/article/details/103492525