Topic was automatically imported from the old Question2Answer platform.
Asked By
Alikae
I have some signal, with potential callables connected to it.
When I emit it, I want to wait for each callback to return before pursuing.
Something like:
await emit_signal('my_sig')
But it return immediatly after launching the callbacks execution.
I think this goes against the idea of signals: Emit upwards in the hierarchy, and don’t worry about whether it’s listened for. I think there are ways around this if you know how many other nodes are listening for the signal.
But I’m implementing the following hack for this:
I have an internal signal called something like signal_handled, and then my child node looks like this:
signal signal_name
signal _signal_handled
@export var number_of_signal_handlers: int = 3
func on_button() -> void:
signal_name.emit()
for i in number_of_signal_handlers:
await _signal_handled
# Whatever you want to happen after the signal handlers have finished.
And my listeners look like this:
onready var child_node
func _ready() -> void:
child_node.signal_name.connect(_handle_signal)
func _handle_signal() -> void:
# Do whatever you want here
child_node._signal_handled.emit()
It’s obviously a fragile solution that’s prone to issues, but in my specific case there’s only one thing listening to the signal and calling the child node’s internal signal.
I think this is kinda in keeping with the idea of coroutines, where control is passed back and forth in the form of ‘cooperative concurrency’.
In case anyone else comes across this thread - I found a fairly neat way to achiece this effect. You can make your own connect_ and emit_ methods and have an Array[Callable] behind the scenes which allows you to await when you emit.
For example, the emitting child:
var _test_listeners :Array[Callable] = []
func test_connect(listener :Callable):
_test_listeners.append(listener)
func test_disconnect(listener :Callable):
var i = _test_listeners.find(listener)
if i >= 0: _test_listeners.remove_at(i)
func _test_emit(message :String):
for listener in _test_listeners:
await listener.call(message)
func do_test():
await _test_emit("hello")
print("emitter - also done waiting")