发布订阅
小于 1 分钟
发布订阅
type eventType = string | symbol;
type eventListener = {
once?: boolean;
listener: Function;
};
type eventListType = Map<eventType, eventListener[]>;
interface EventEmitter {
on(
event: eventType,
listener: eventListener['listener'],
once: eventListener['once']
): () => void;
off(event: eventType, listener: eventListener['listener']): void;
emit(event: eventType, ...args: any[]): void;
once(event: eventType, listener: eventListener['listener']): void;
}
class EventEmitter implements EventEmitter {
private eventList: eventListType = new Map();
on(event: eventType, listener: Function, once: boolean = false) {
const eventWatchList = this.eventList.get(event);
if (eventWatchList) {
eventWatchList.push({
listener,
once,
});
this.eventList.set(event, eventWatchList);
} else {
this.eventList.set(event, [
{
listener,
once,
},
]);
}
return () => {
this.off(event, listener);
};
}
off(event: eventType, listener: Function) {
const eventWatchList = this.eventList.get(event);
if (!eventWatchList) return;
this.eventList.set(
event,
eventWatchList.filter((item) => item.listener !== listener)
);
}
emit(event: eventType, ...args: any[]): void {
const eventWatchList = this.eventList.get(event);
if (!eventWatchList) return;
eventWatchList.forEach(({ listener, once }) => {
listener(...args);
once && this.off(event, listener);
});
}
once(event: eventType, listener: Function) {
this.on(event, listener, true);
}
}
const emit = new EventEmitter();
class Person {
constructor(public name: string) {}
subscribe(type: string, handle: Function) {
emit.on(type, handle.bind(this));
}
notify(type: string, handle: Function) {
emit.emit(type, handle.call(this));
}
}
const xm = new Person('xm');
const zs = new Person('zs');
const ls = new Person('ls');
xm.subscribe('eat', function (this: Person, ...args: any[]) {
console.log(this.name, 'eat', ...args);
});
zs.subscribe('eat', function (this: Person, ...args: any[]) {
console.log(this.name, 'eat', ...args);
});
xm.subscribe('eat', function (this: Person, ...args: any[]) {
console.log(this.name, 'eat', ...args);
});
zs.notify('eat', function (this: Person) {
return {
name: this.name,
see: '走出去玩',
};
});