event_emitter
Event Emitter (FORKED)
This is a Generically typed version of @hugoabonizio's Event Emitter.
As of yet, only
EventEmitter::Base
has been converted to a Generic type. This fork may move into an independent repository as it grows. I forked because I needed a way to dynamically emit events, and CrystalSymbol
's can't be dynamically instantiated.
EventEmitter provides an idiomatic asynchronous event-driven architecture by registering listener functions that are called by named event emits. This shard is heavily inspired by Node.js events API.
When the emit
method is called, the listeners attached to it will be called (synchronously or asynchronously) with the possibility to pass arguments to it.
The following example shows a simple EventEmitter usage with a single listener.
require "event_emitter"
class MyEmitter
include EventEmitter::DSL
on :connect, sync: true do |name|
puts "Hello #{name}"
end
def connect(name)
emit :connect, name
end
end
emitter = MyEmitter.new
emitter.connect("Hugo")
Another approach is to inherit from EventEmitter::Base
class, as the example above:
class MyEmitter < EventEmitter::Base(Symbol, String); end
my = MyEmitter.new
my.on :event, ->(name : EventEmitter::Base::Any) do
puts "Hello #{name}"
end
my.emit :event, "hugo"
my.emit :event, "abonizio"
Usage
DSL
Synchronous and asynchronous
A listener can execute a block synchronously or asynchronously depending on the argument sync
it is passed.
# Asynchronous (executed in another fiber)
on :message, do |message|
puts "ASYNC: Message: #{message}"
end
# Synchronous
on :connect, sync: true do |name|
puts "SYNC: Hello #{name}"
end
Passing arguments to the listeners
class MyEmitter
include EventEmitter::DSL
on :finish do |id, name|
puts "Hello #{name} (#{id})"
end
def perform(name)
id = User.create(name)
emit :finish, id, name
end
end
Multiple listeners
It is possible to register more than one listener to a given event by calling previous_def inside the block making the blocks stackable. If the listeners are async, each one is executed in its own fiber concurrently.
on :message do |message|
previous_def(message)
log "Message received: #{message}"
end
Instance
The class EventEmitter::Base
provides the methods on
, once
and emit
to insert a new listener, insert a one-time listener and trigger an event, respectively.
You can inherit from EventEmitter::Base
class to add custom functionality (class MyEmitter < EventEmitter::Base; end
) or simply create an instance of EventEmitter::Base
as the following example.
emitter = EventEmitter::Base(Symbol, String).new
emitter.on :message, ->(body : EventEmitter::Base::Any) do
puts "> #{body}"
end
delay 200.milliseconds do
emitter.emit :message, "Hello, world!"
end
Handling events only once:
emitter = EventEmitter::Base(Symbol, String).new
flag = 1
emitter.once :trigger do
flag = 2
end
emitter.emit :trigger
emitter.emit :trigger # Will execute only the first trigger
Installation
Add this to your application's shard.yml
:
dependencies:
event_emitter:
github: mccallofthewild/event_emitter.cr
Contributing
- Fork it ( https://github.com/mccallofthewild/event_emitter.cr/fork )
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
Contributors
- hugoabonizio Hugo Abonizio - creator, maintainer
- mccallofthewild McCall Alexander - customizer, maintainer