Event hub using promises so event listeners can throw errors / return values to the event emitter