Как сделать передачу аргументов?
Как правильно сделать, чтобы проходил тест?
Задание: Cоздайте класс EventEmitter для управления событиями. У этого класса должны быть следующие методы: .on(event, callback) - добавить обработчик события
.off(event, callback) - удалить обработчик события
.once(event, callback) - добавить обработчик события, который сработает единожды
.emit(event, [...arg]) - вызвать все обработчики события event, можно передать аргументы
Расширьте EventEmitter классом BroadcastEventEmitter так, чтобы была возможность вызвать все обработчики всех событий: emit("*", [...arg]) - вызвать все обработчики событий, можно передать аргументы
class EventEmitter {
constructor() {
this.events = {};
}
on(eventName, callback) {
!this.events[eventName] && (this.events[eventName] = []);
this.events[eventName].push(callback);
}
off(eventName, callback) {
this.events[eventName] = this.events[eventName].filter(eventCallback => callback !== eventCallback);}
once(eventName, callback) {
this.events[eventName] = this.events[eventName] || [];
const onceEvent = () => {
callback();
this.off(eventName, onceEvent);
}
this.events[eventName].push(onceEvent);
return this;
}
emit(eventName, args) {
const event = this.events[eventName];
event && event.forEach(callback => callback.call(null, args));
}
}
class BroadcastEventEmitter extends EventEmitter {
emit(event, ...args) {
if (event === '*') {
Object.keys(this.events).forEach((e) => super.emit(e, ...args));
} else {
super.emit(event, ...args);
}
}}
Не проходит тест:
тестирование класса BroadcastEventEmitter
✓ проверка наследования от EventEmitter (1ms)
✓ вызов всех событий
✕ передача аргументов (4ms)
● тестирование класса BroadcastEventEmitter › передача аргументов
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: 1, 2
Received: 1
Number of calls: 1
163 | emitter.emit('*', ...args);
164 |
> 165 | expect(mockFirstListener).toHaveBeenCalledWith(...args);
| ^
166 | expect(mockSecondListener).toHaveBeenCalledWith(...args);
167 | });
168 | });
at Object.toHaveBeenCalledWith test.js:165:31)
Ответы (2 шт):
В методе BroadcastEventEmitter.emit, в обращении к методу наследующего класса super.emit(event, ...args), для передачи использовался оператор rest. Из-за него передавался только 1 аргумент, самый первый.
class EventEmitter {
constructor() {
this.events = {};
}
on(eventName, callback) {
!this.events[eventName] && (this.events[eventName] = []);
this.events[eventName].push(callback);
}
off(eventName, callback) {
this.events[eventName] = this.events[eventName].filter(eventCallback => callback !== eventCallback);
}
once(eventName, callback) {
this.events[eventName] = this.events[eventName] || [];
const onceEvent = (args) => {
callback.call(onceEvent, args);
this.off(eventName, onceEvent);
};
this.events[eventName].push(onceEvent);
return this;
}
emit(eventName, ...args) {
const event = this.events[eventName];
event && event.forEach(callback => callback.call(null, ...args));
}
}
class BroadcastEventEmitter extends EventEmitter {
emit(event, ...args) {
if (event !== '*') return void(super.emit(event, args));
Object.keys(this.events).forEach((e) => super.emit(e, args));
}
}
const emitter = new BroadcastEventEmitter();
emitter.on('event', (args) => console.log(args));
emitter.once('event3', (args) => console.log(args));
emitter.emit('event3', 1, 2, 3, 4, 5);
emitter.emit('event', 1, 2, 3, 4, 5);
Попробуйте, прогоните через тест, если что, поправлю ответ.
class EventEmitter {
constructor() {
this.events = {};
}
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
off(eventName, callback) {
if (!this.events[eventName]) return;
this.events[eventName] = this.events[eventName].filter(
eventCallback => callback !== eventCallback);
}
once(eventName, callback) {
const onceEvent = (...args) => {
callback.apply(null, args);
this.off(eventName, onceEvent);
};
this.on(eventName, onceEvent);
}
emit(eventName, ...args) {
const event = this.events[eventName];
if (event) {
event.forEach((callback) => callback.apply(null, args));
}
}
}
class BroadcastEventEmitter extends EventEmitter {
emit(event, ...args) {
if (event !== '*') {
super.emit(event, ...args);
} else {
Object.keys(this.events).forEach((e) => super.emit(e, ...args));
}
}
}
Я сейчас решал эту задачу, вот самый верный и рабочий ответ. Уверен будущим поколениям пригодится