Is it possible to await the Callables connected to a signal when it is emitted ? (Godot 4)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: 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.

Complete example:

extends Node

signal sig()

func _ready():
    await emit_signal('sig')
    print('emitted !')

func _on_sig():
    await get_tree().create_timer(1).timeout
    print('sig waited')

Is it possible using GDScript signal’s implementation, or should I implement my own Publisher-Subscriber ?

:bust_in_silhouette: Reply From: IMP1

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:
    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:

func _handle_signal() -> void:
    # Do whatever you want here

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’.