Last active
November 27, 2019 01:37
-
-
Save james4388/26e47ee773bfa1f4050d82b766e261d3 to your computer and use it in GitHub Desktop.
Implement EventEmitter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class EventEmitter { | |
constructor (isAsync = false) { | |
this.events = new Map(); | |
this.isAsync = isAsync; // Allow to notify listener async | |
} | |
/* | |
* Subcribe a callback to an event. Callback will not be duplicate. | |
* return unsibcribe function | |
* Usage: const unsub = ee.subcribe(eventName, callback); | |
* To unsubcribe: unsub() | |
*/ | |
subcribe (event, callback) { | |
const listeners = this.events.get(event) || new Set(); | |
listeners.add(callback); | |
this.events.set(event, listeners); | |
return this.unsubcribe.bind(this, event, callback); | |
} | |
unsubcribe (event, callback) { | |
const listeners = this.events.get(event); | |
if (listeners !== undefined) { | |
listeners.delete(callback); | |
} | |
} | |
emit (event, ...args) { | |
const listeners = this.events.get(event); | |
if (listeners !== undefined) { | |
// if a callback got unsubcribe while iterate it wont' get call | |
// use [...listeners].forEach to prevent this. | |
if (this.isAsync) { | |
// Wrap callback inside promises for async call | |
Promise.all( | |
[...listeners].map( | |
async (callback) => new Promise((approve, reject) => { | |
approve(callback.apply(null, args)); | |
}) | |
) | |
); | |
} else { | |
listeners.forEach((callback) => { | |
try { | |
callback.apply(null, args); | |
} catch (err) { | |
// Do something. | |
} | |
}); | |
} | |
} | |
} | |
} | |
/* Async test */ | |
async function sleep(ms) { | |
return new Promise(resolve => setTimeout(resolve, ms)); | |
} | |
const ee = new EventEmitter(true); | |
const unsub1 = ee.subcribe('test', async () => { | |
await sleep(2000); | |
console.log('Sub1'); | |
}); | |
const unsub2 = ee.subcribe('test', () => {console.log('Sub2')}); | |
const unsub3 = ee.subcribe('test', () => {console.log('Sub3')}); | |
ee.emit('test') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment