Module: Events::Emitter
- Included in:
- EventEmitter
- Defined in:
- lib/events.rb
Overview
The Events::Emitter mixin provides a clone of the Node.js EventEmitter API for Ruby.
Instances of classes including Events::Emitter will emit events, events are represented by symbols, underscored in the usual Ruby fashion. Examples: :connection, :data, :message_begin
Blocks can be attached to objects to be executed when an event is emitted, these blocks are called listeners.
All EventEmitters emit the event :new_listener when new listeners are added, this listener is provided with the event and new listener added. Example:
server.on(:new_listener) do |event, listener|
puts "added new listener #{listener} for event #{event}"
end
server.on(:connection) do |socket|
puts "someone connected!"
end
Outputs “added new listener #<Proc:[email protected]:12> for event connection”.
When an EventEmitter experiences an error, the typical action is to emit an :error event. Error events are special – if there is no handler for them they raise an Events::UncaughtError exception.
Defined Under Namespace
Classes: Listeners, OnceWrapper
Constant Summary collapse
- DEFAULT_MAX_LISTENERS =
10
Instance Method Summary collapse
-
#add_listener(event, proc = nil, &block) ⇒ Object
(also: #on)
:call-seq: emitter.on(event) {|args…| block} -> emitter emitter.on(event, proc) -> emitter.
-
#emit(event, *args) ⇒ Object
:call-seq: emitter.emit(event[, arguments…]) -> bool.
-
#listeners(event) ⇒ Object
:call-seq: emitter.listeners(event) -> array.
-
#max_listeners=(value) ⇒ Object
(also: #set_max_listeners)
:call-seq: emitter.max_listeners = integer -> integer.
-
#once(event, proc = nil, &block) ⇒ Object
:call-seq: emitter.once(event) {|args…| block} -> emitter emitter.once(event, proc) -> emitter.
-
#remove_all_listeners(event = :_remove_all_listeners_default_arg_) ⇒ Object
:call-seq: emitter.remove_all_listeners -> emitter emitter.remove_all_listeners(event) -> emitter.
-
#remove_listener(event, proc) ⇒ Object
:call-seq: emitter.remove_listener(event, proc) -> emitter.
Instance Method Details
#add_listener(event, proc = nil, &block) ⇒ Object Also known as: on
:call-seq: emitter.on(event) {|args…| block} -> emitter emitter.on(event, proc) -> emitter
Adds a listener to the end of the listeners array for the specified event.
server.on(:connection) do |socket|
puts "someone connected!"
end
Rather than a block, can take a second argument of a Proc (or any object with a #call method).
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/events.rb', line 99 def add_listener(event, proc=nil, &block) listener = proc || block unless listener.respond_to?(:call) raise ArgumentError.new("Listener must respond to #call") end emit(:new_listener, event, listener) event_listeners = listeners(event) event_listeners.push(listener) current = event_listeners.length if max_listeners > 0 && current > max_listeners && !event_listeners.warned warn(caller[1] + ": warning: possible EventEmitter memory leak detected. " << "#{current} listeners added. " << "Use Emitter#max_listeners = n to increase limit.") event_listeners.warned = true end self end |
#emit(event, *args) ⇒ Object
:call-seq: emitter.emit(event[, arguments…]) -> bool
Execute each of the listeners in order with the supplied arguments.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/events.rb', line 72 def emit(event, *args) listeners = @listeners && @listeners.key?(event) && @listeners[event] if event == :error && (!listeners || listeners.empty?) raise *args if args.first.respond_to?(:exception) raise Events::UncaughtError, args.first if args.first.is_a?(String) raise Events::UncaughtError.new("Uncaught, unspecified 'error' event.") elsif listeners listeners.dup.each do |listener| listener.call(*args) end.any? else false end end |
#listeners(event) ⇒ Object
:call-seq: emitter.listeners(event) -> array
Returns an array of listeners for the specified event. This array can be manipulated, e.g. to remove listeners.
64 65 66 |
# File 'lib/events.rb', line 64 def listeners(event) (@listeners ||= Hash.new {|hash, key| hash[key] = Listeners.new})[event] end |
#max_listeners=(value) ⇒ Object Also known as: set_max_listeners
:call-seq: emitter.max_listeners = integer -> integer
By default an EventEmitter will print a warning if more than 10 listeners are added to it. This is a useful default which helps finding memory leaks. Obviously not all Emitters should be limited to 10. This method allows that to be increased. Set to zero for unlimited.
54 55 56 |
# File 'lib/events.rb', line 54 def max_listeners=(value) @max_listeners = value end |
#once(event, proc = nil, &block) ⇒ Object
:call-seq: emitter.once(event) {|args…| block} -> emitter emitter.once(event, proc) -> emitter
Adds a one time listener for the event. The listener is invoked only the first time the event is fired, after which it is removed.
server.once(:connection) do |socket|
puts "Ah, we have our first user!"
end
131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/events.rb', line 131 def once(event, proc=nil, &block) listener = proc || block unless listener.respond_to?(:call) raise ArgumentError.new("Listener must respond to #call") end once = OnceWrapper.new do |*args| remove_listener(event, once) listener.call(*args) end once.original = listener add_listener(event, once) end |
#remove_all_listeners(event = :_remove_all_listeners_default_arg_) ⇒ Object
:call-seq: emitter.remove_all_listeners -> emitter emitter.remove_all_listeners(event) -> emitter
Removes all listeners, or those of the specified event.
164 165 166 167 168 169 170 171 |
# File 'lib/events.rb', line 164 def remove_all_listeners(event=:_remove_all_listeners_default_arg_) @listeners = nil if event == :_remove_all_listeners_default_arg_ if @listeners && @listeners.key?(event) @listeners[event].clear @listeners.delete(event) end self end |
#remove_listener(event, proc) ⇒ Object
:call-seq: emitter.remove_listener(event, proc) -> emitter
Remove a listener from the listener array for the specified event.
149 150 151 152 153 154 155 156 157 |
# File 'lib/events.rb', line 149 def remove_listener(event, proc) if @listeners && @listeners.key?(event) @listeners[event].delete_if do |lis| lis == proc || lis.respond_to?(:original) && lis.original == proc end @listeners.delete(event) if @listeners[event].empty? end self end |