Skip to main content

Signal

A Signal is a data structure that allows events to be dispatched and observed.

This implementation is a direct copy of the de facto standard, GoodSignal, with some added methods and typings.

For example:

local signal = Signal.new()

-- Subscribe to a signal:
signal:Connect(function(msg)
	print("Got message:", msg)
end)

-- Dispatch an event:
signal:Fire("Hello world!")

Types

SignalConnection

interface SignalConnection {
Connectedboolean
Disconnect(SignalConnection) → ()
}

Represents a connection to a signal.

local connection = signal:Connect(function() end)
print(connection.Connected) --> true
connection:Disconnect()
print(connection.Connected) --> false

ConnectionFn

type ConnectionFn = (...any) → ()

A function connected to a signal.

Functions

new

Signal.new() → Signal

Constructs a new Signal

Wrap

Signal.Wrap(
rbxScriptSignalRBXScriptSignal--

Existing RBXScriptSignal to wrap

) → Signal

Constructs a new Signal that wraps around an RBXScriptSignal.

For example:

local signal = Signal.Wrap(workspace.ChildAdded)
signal:Connect(function(part) print(part.Name .. " added") end)
Instance.new("Part").Parent = workspace

Is

Signal.Is(
objany--

Object to check

) → boolean--

true if the object is a Signal.

Checks if the given object is a Signal.

Connect

Signal:Connect(fnConnectionFn) → SignalConnection

Connects a function to the signal, which will be called anytime the signal is fired.

signal:Connect(function(msg, num)
	print(msg, num)
end)

signal:Fire("Hello", 25)

Once

Signal:Once(fnConnectionFn) → SignalConnection

Connects a function to the signal, which will be called the next time the signal fires. Once the connection is triggered, it will disconnect itself.

signal:Once(function(msg, num)
	print(msg, num)
end)

signal:Fire("Hello", 25)
signal:Fire("This message will not go through", 10)

DisconnectAll

Signal:DisconnectAll() → ()

Disconnects all connections from the signal.

signal:DisconnectAll()

Fire

Signal:Fire(...any) → ()

Fire the signal, which will call all of the connected functions with the given arguments.

signal:Fire("Hello")

-- Any number of arguments can be fired:
signal:Fire("Hello", 32, {Test = "Test"}, true)

FireDeferred

Signal:FireDeferred(...any) → ()

Same as Fire, but uses task.defer internally & doesn't take advantage of thread reuse.

signal:FireDeferred("Hello")

Wait

This is a yielding function. When called, it will pause the Lua thread that called the function until a result is ready to be returned, without interrupting other scripts. Yields
Signal:Wait() → ...any

Yields the current thread until the signal is fired, and returns the arguments fired from the signal. Yielding the current thread is not always desirable. If the desire is to only capture the next event fired, using Once might be a better solution.

task.spawn(function()
	local msg, num = signal:Wait()
	print(msg, num) --> "Hello", 32
end)
signal:Fire("Hello", 32)

Destroy

Signal:Destroy() → ()

Cleans up the signal.

Technically, this is only necessary if the signal is created using Signal.Wrap. Connections should be properly GC'd once the signal is no longer referenced anywhere. However, it is still good practice to include ways to strictly clean up resources. Calling Destroy on a signal will also disconnect all connections immediately.

signal:Destroy()

ConnectOnce

deprecated in v1.3.0
</>
This was deprecated in v1.3.0

Use `Signal:Once` instead.

Signal:ConnectOnce(fnConnectionFn) → SignalConnection
Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Constructs a new Signal",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Signal"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 153,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "Wrap",
            "desc": "Constructs a new Signal that wraps around an RBXScriptSignal.\n\n\nFor example:\n```lua\nlocal signal = Signal.Wrap(workspace.ChildAdded)\nsignal:Connect(function(part) print(part.Name .. \" added\") end)\nInstance.new(\"Part\").Parent = workspace\n```",
            "params": [
                {
                    "name": "rbxScriptSignal",
                    "desc": "Existing RBXScriptSignal to wrap",
                    "lua_type": "RBXScriptSignal"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Signal"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 176,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "Is",
            "desc": "Checks if the given object is a Signal.",
            "params": [
                {
                    "name": "obj",
                    "desc": "Object to check",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "`true` if the object is a Signal.",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 196,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "Connect",
            "desc": "Connects a function to the signal, which will be called anytime the signal is fired.\n```lua\nsignal:Connect(function(msg, num)\n\tprint(msg, num)\nend)\n\nsignal:Fire(\"Hello\", 25)\n```",
            "params": [
                {
                    "name": "fn",
                    "desc": "",
                    "lua_type": "ConnectionFn"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "SignalConnection"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 213,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "ConnectOnce",
            "desc": "",
            "params": [
                {
                    "name": "fn",
                    "desc": "",
                    "lua_type": "ConnectionFn"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "SignalConnection"
                }
            ],
            "function_type": "method",
            "deprecated": {
                "version": "v1.3.0",
                "desc": "Use `Signal:Once` instead."
            },
            "source": {
                "line": 236,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "Once",
            "desc": "Connects a function to the signal, which will be called the next time the signal fires. Once\nthe connection is triggered, it will disconnect itself.\n```lua\nsignal:Once(function(msg, num)\n\tprint(msg, num)\nend)\n\nsignal:Fire(\"Hello\", 25)\nsignal:Fire(\"This message will not go through\", 10)\n```",
            "params": [
                {
                    "name": "fn",
                    "desc": "",
                    "lua_type": "ConnectionFn"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "SignalConnection"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 255,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "DisconnectAll",
            "desc": "Disconnects all connections from the signal.\n```lua\nsignal:DisconnectAll()\n```",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 292,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "Fire",
            "desc": "Fire the signal, which will call all of the connected functions with the given arguments.\n```lua\nsignal:Fire(\"Hello\")\n\n-- Any number of arguments can be fired:\nsignal:Fire(\"Hello\", 32, {Test = \"Test\"}, true)\n```",
            "params": [
                {
                    "name": "...",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 327,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "FireDeferred",
            "desc": "Same as `Fire`, but uses `task.defer` internally & doesn't take advantage of thread reuse.\n```lua\nsignal:FireDeferred(\"Hello\")\n```",
            "params": [
                {
                    "name": "...",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 348,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "Wait",
            "desc": "Yields the current thread until the signal is fired, and returns the arguments fired from the signal.\nYielding the current thread is not always desirable. If the desire is to only capture the next event\nfired, using `Once` might be a better solution.\n```lua\ntask.spawn(function()\n\tlocal msg, num = signal:Wait()\n\tprint(msg, num) --> \"Hello\", 32\nend)\nsignal:Fire(\"Hello\", 32)\n```",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "... any"
                }
            ],
            "function_type": "method",
            "yields": true,
            "source": {
                "line": 376,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "Destroy",
            "desc": "Cleans up the signal.\n\nTechnically, this is only necessary if the signal is created using\n`Signal.Wrap`. Connections should be properly GC'd once the signal\nis no longer referenced anywhere. However, it is still good practice\nto include ways to strictly clean up resources. Calling `Destroy`\non a signal will also disconnect all connections immediately.\n```lua\nsignal:Destroy()\n```",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 406,
                "path": "modules/signal/init.luau"
            }
        }
    ],
    "properties": [],
    "types": [
        {
            "name": "SignalConnection",
            "desc": "Represents a connection to a signal.\n```lua\nlocal connection = signal:Connect(function() end)\nprint(connection.Connected) --> true\nconnection:Disconnect()\nprint(connection.Connected) --> false\n```",
            "fields": [
                {
                    "name": "Connected",
                    "lua_type": "boolean",
                    "desc": ""
                },
                {
                    "name": "Disconnect",
                    "lua_type": "(SignalConnection) -> ()",
                    "desc": ""
                }
            ],
            "source": {
                "line": 76,
                "path": "modules/signal/init.luau"
            }
        },
        {
            "name": "ConnectionFn",
            "desc": "A function connected to a signal.",
            "lua_type": "(...any) -> ()",
            "source": {
                "line": 122,
                "path": "modules/signal/init.luau"
            }
        }
    ],
    "name": "Signal",
    "desc": "A Signal is a data structure that allows events to be dispatched\nand observed.\n\nThis implementation is a direct copy of the de facto standard, [GoodSignal](https://devforum.roblox.com/t/lua-signal-class-comparison-optimal-goodsignal-class/1387063),\nwith some added methods and typings.\n\nFor example:\n```lua\nlocal signal = Signal.new()\n\n-- Subscribe to a signal:\nsignal:Connect(function(msg)\n\tprint(\"Got message:\", msg)\nend)\n\n-- Dispatch an event:\nsignal:Fire(\"Hello world!\")\n```",
    "source": {
        "line": 145,
        "path": "modules/signal/init.luau"
    }
}