我正在尝试实现一个有四种方法的自定义Emitter类。所有工作除了一次。
我需要实施返回的'once'
方法 事件名称的当前订阅者数量。
once方法的当前行为是事件正在添加但未被删除或调用。
class Emitter {
constructor() {
//Arrays of objects
this.events = {};
}
on(eventName, callBack) {
//If the event name is not a string data type throw error
if (typeof eventName !== 'string') throw 'Event name is not a String';
// If the callback is not a function data type throw error
if (typeof callBack !== 'function') throw 'Callback is not a Function';
let event = this.events[eventName];
// If eventName is already defined then push the callback, else create
!event ? this.events[eventName] = [callBack] : event.push(callBack);
//this.events[eventName] ? this.events[eventName].push(callBack) : this.events[eventName] = [callBack];
return this.events[eventName].length;
}
off(eventName, callBack) {
//If there are two arguments provided then, callback must be there!
let isCallBackDefined = arguments.length === 2 ? true : false;
//If the event name is not a string data type throw error
if (typeof eventName !== 'string') throw 'Event name is not a String';
// If the function is not a function data type (if provided) throw error
if (isCallBackDefined && typeof callBack !== 'function') throw 'Callback is not a Function';
// First get the correct event
let event = this.events[eventName];
// Check that the event exists and it has the callback registered
if (event) {
// if no callback function provided, then all functions are unsubscribed
// event has no callbacks left, delete the event
if (isCallBackDefined === false) {
delete this.events[eventName];
} else {
// if it is registered then unregister it!
const index = event.indexOf(callBack);
// If the callback is in the array then remove it
if (index > -1) {
event.splice(index, 1);
}
// if the event has no callbacks left, delete the event
if (event.length === 0) {
delete this.events[eventName];
}
}
}
return (this.events[eventName] || []).length;
}
trigger(eventName, ...args) {
if (typeof eventName !== 'string') throw TypeError('Event name is not a String');
let listeners;
// If the event exists; create a shallow copy
if (this.events[eventName]) {
listeners = this.events[eventName].slice();
}
// Check that the event exists and it has the callback registered
if (listeners) {
for (let callBack of listeners) {
callBack.apply(this, args);
}
}
return listeners ? true : false;
}
once(event, fn) {
//If the event name is not a string data type throw error
if (typeof event !== 'string') throw 'Event name is not a String';
// If the callback is not a function data type throw error
if (typeof fn !== 'function') throw 'Callback is not a Function';
function g() {
this.off(event, g);
fn.apply(this, arguments);
}
g.fn = fn;
this.on(event, g);
};
}
答案 0 :(得分:0)
您只需返回事件名称的回调数。我在控制台中添加了一些“测试”,以便您确认。
class Emitter {
constructor() {
//Arrays of objects
this.events = {};
}
on(eventName, callBack) {
//If the event name is not a string data type throw error
if (typeof eventName !== 'string') throw 'Event name is not a String';
// If the callback is not a function data type throw error
if (typeof callBack !== 'function') throw 'Callback is not a Function';
let event = this.events[eventName];
// If eventName is already defined then push the callback, else create
!event ? this.events[eventName] = [callBack] : event.push(callBack);
//this.events[eventName] ? this.events[eventName].push(callBack) : this.events[eventName] = [callBack];
return this.events[eventName].length;
}
off(eventName, callBack) {
//If there are two arguments provided then, callback must be there!
let isCallBackDefined = arguments.length === 2 ? true : false;
//If the event name is not a string data type throw error
if (typeof eventName !== 'string') throw 'Event name is not a String';
// If the function is not a function data type (if provided) throw error
if (isCallBackDefined && typeof callBack !== 'function') throw 'Callback is not a Function';
// First get the correct event
let event = this.events[eventName];
// Check that the event exists and it has the callback registered
if (event) {
// if no callback function provided, then all functions are unsubscribed
// event has no callbacks left, delete the event
if (isCallBackDefined === false) {
delete this.events[eventName];
} else {
// if it is registered then unregister it!
const index = event.indexOf(callBack);
// If the callback is in the array then remove it
if (index > -1) {
event.splice(index, 1);
}
// if the event has no callbacks left, delete the event
if (event.length === 0) {
delete this.events[eventName];
}
}
}
return (this.events[eventName] || []).length;
}
trigger(eventName, ...args) {
if (typeof eventName !== 'string') throw TypeError('Event name is not a String');
let listeners;
// If the event exists; create a shallow copy
if (this.events[eventName]) {
listeners = this.events[eventName].slice();
}
// Check that the event exists and it has the callback registered
if (listeners) {
for (let callBack of listeners) {
callBack.apply(this, args);
}
}
return listeners ? true : false;
}
once(event, fn) {
//If the event name is not a string data type throw error
if (typeof event !== 'string') throw 'Event name is not a String';
// If the callback is not a function data type throw error
if (typeof fn !== 'function') throw 'Callback is not a Function';
function g() {
this.off(event, g);
fn.apply(this, arguments);
}
g.fn = fn;
this.on(event, g);
return this.events[event].length;
// ^^ Return the current number of subscribers
};
}
// Test it!
let fnCallCount = 0;
let fnArgs = null;
const fn = (...args) => {
fnCallCount += 1;
fnArgs = args;
}
const sut = new Emitter();
sut.trigger('test', 1, 2, 3);
console.log("Number of subscribers ('test'):", sut.once('test', fn)); // Expecting 1
console.log("Number of subscribers ('next'):", sut.once('next', ()=>{})); // Expecting 1
console.log("Number of subscribers ('next'):", sut.once('next', ()=>{})); // Expecting 2
console.log("Call count after first event:", fnCallCount); // Expecting 1
console.log("Call args:", fnArgs); // Expecting [1,2,3]
sut.trigger('test', 1, 2, 3);
console.log("Call count after second event:", fnCallCount); // Expecting 1