-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
event_callbackable.rb
103 lines (89 loc) · 2.56 KB
/
event_callbackable.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
require 'securerandom'
module Puppeteer::EventCallbackable
class EventListeners
include Enumerable
def initialize
@listeners = {}
end
# @return [String] Listener ID
def add(&block)
id = SecureRandom.hex(8)
@listeners[id] = block
id
end
# @param id [String] Listener ID returned on #add
def delete(id)
@listeners.delete(id)
end
# @implement Enumerable#each
def each(&block)
@listeners.values.each(&block)
end
end
def add_event_listener(event_name, &block)
@event_listeners ||= {}
(@event_listeners[event_name] ||= EventListeners.new).add(&block)
end
alias_method :on, :add_event_listener
def remove_event_listener(*id_args)
(@event_listeners ||= {}).each do |event_name, listeners|
id_args.each do |id|
listeners.delete(id)
end
end
end
def observe_first(event_name, &block)
listener_id = add_event_listener(event_name) do |*args, **kwargs|
if kwargs.empty?
block.call(*args)
else
block.call(*args, **kwargs)
end
remove_event_listener(listener_id)
end
end
alias_method :once, :observe_first
def on_event(event_name, &block)
@event_callbackable_handlers ||= {}
@event_callbackable_handlers[event_name] = block
end
def emit_event(event_name, *args, **kwargs)
@event_callbackable_handlers ||= {}
@event_listeners ||= {}
if kwargs.empty?
# In Ruby's specification (version < 2.7),
# `method(:x).call(*args, **kwargs)` is equivalent to `x(*args, {})`
# It often causes unexpected ArgumentError.
#
# ----------------
# def greet
# puts 'Hello!'
# end
#
# def call_me(*args, **kwargs)
# greet(*args, **kwargs) # => 'Hello!'
#
# method(:greet).call(*args, **kwargs) # => `greet': wrong number of arguments (given 1, expected 0) (ArgumentError)
# end
#
# call_me
# ----------------
#
# This behavior is really annoying, and should be avoided, because we often want to set event handler as below:
#
# `on_event 'Some.Event.awesome', &method(:handle_awesome_event)`
#
# So Let's avoid it by checking kwargs.
@event_callbackable_handlers[event_name]&.call(*args)
@event_listeners[event_name]&.each do |proc|
proc.call(*args)
end
else
@event_callbackable_handlers[event_name]&.call(*args, **kwargs)
@event_listeners[event_name]&.each do |proc|
proc.call(*args, **kwargs)
end
end
event_name
end
end