Lua Advanced: Coroutines, Metamethods & Performance

Lesson 5 of 5

Final Project: Build a Tiny Event Emitter with Coroutines

Combine coroutines, metatables, and varargs into a small pub/sub event emitter, a pattern used constantly in game engines and GUI frameworks.

Requirements

  1. Build an EventEmitter "class" (metatable-based, like earlier OOP lessons) with on(event, handler), off(event, handler), and emit(event, ...) methods. emit should forward any extra arguments straight to every registered handler using varargs.
  2. Support multiple handlers per event name, stored in a table keyed by event name, each holding a list of handler functions.
  3. Wrap each handler call in pcall inside emit, so one broken handler doesn't stop the rest of that event's handlers from running, log a warning for the failing one instead.
  4. Add an onceAsync(event) method that returns a coroutine-based helper: calling it pauses (via coroutine.yield) until the named event next fires, then resumes with that event's arguments, essentially turning a callback-style event into something you can "await" step by step.
  5. Use a weak table (__mode = "k") to track any per-listener metadata you add (e.g. a registration timestamp) so that metadata doesn't keep a removed handler function alive forever.

Stretch goals

  • Add wildcard subscriptions (emitter:on("*", handler) fires on every event).
  • Add a once(event, handler) convenience method that automatically calls off after the handler's first invocation.
  • Benchmark emitting 10,000 events with os.clock() before and after switching a hot path from pairs to ipairs where applicable, and note the difference.

Submit a link to your finished script (a repo or gist) below, an instructor will review it before you can mark this lesson complete.

This lesson ends in a project. Build it on your own machine, there's nowhere to submit it here, but the brief above is everything you need.