lloyAlloy on GitHub
Signal
Docs

Signal

Updated
Signal<T...>
import { Signal } from "@alloy/std/signal"

local player = game:GetService("Players").LocalPlayer
local damaged = new Signal<<Player, number>>()
local conn = damaged:Connect(function(who, amount) end)
damaged:Fire(player, 10)
local who, amount = damaged:Wait(5)

A typed signal, from the std, with the shape of RBXScriptSignal, so code that takes one takes the other. Signal.new<T...>() fires T...; handlers run in connection order, each on a reused thread, and a handler may disconnect any connection during a fire.

Each has a snake_case twin, connect, once, wait, fire, fire_deferred, disconnect_all, destroy. A connection has Connected, Disconnect, and disconnect. Signal.is(value) says whether a value is one.

Signal.collect(source) turns any signal with Connect or connect, the shape Signalish<T...>, a Roblox one included, into an iterator that drains the queued events in order, plus the connection: for id, value in Signal.collect(changed) do. Signal.wrap(source) gives a Signal that fires with the source.

Statics

Signal.new

Signal.new<T...>(): Signal<T...>

A signal that fires T.... The pack takes no explicit type arguments at the call, so write them with <<...>> or on the binding.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
damaged:Fire(10)

Signal.is

Signal.is(value: any): boolean

Whether value is one of the std's signals. An RBXScriptSignal is not.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
print(Signal.is(damaged))

Signal.wrap

Signal.wrap<T...>(source: Signalish<T...>): Signal<T...>

A std Signal that fires whenever source does. source is anything with Connect or connect, a Roblox signal included.

import { Signal } from "@alloy/std/signal"

local source = new Signal<<number>>()
local mine = Signal.wrap(source)
print(Signal.is(mine))

Signal.collect

Signal.collect<T...>(source: Signalish<T...>): ((...any) -> T..., SignalConnection)

An iterator that drains the queued events of source in order, and the connection that feeds it. Disconnect it when the loop ends.

import { Signal } from "@alloy/std/signal"

local changed = new Signal<<number>>()
local events, conn = Signal.collect(changed)
changed:Fire(1)
print(events(), conn.Connected)

Methods

Signal:Connect

Signal:Connect(handler: (T...) -> ()): SignalConnection

Runs handler on every fire and returns the connection. Handlers run in connection order, each on a reused thread.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
local conn = damaged:Connect(function(amount) print(amount) end)
conn:Disconnect()

Signal:Once

Signal:Once(handler: (T...) -> ()): SignalConnection

Runs handler on the next fire alone, then disconnects itself.

import { Signal } from "@alloy/std/signal"

local ready = new Signal<<>>()
ready:Once(function() print("go") end)

Signal:Wait

Signal:Wait(timeout: number?): T...

Yields until the next fire and returns its values. With a timeout it returns nothing when the time runs out.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
local amount = damaged:Wait(5)
print(amount)

Signal:Fire

Signal:Fire(...: T...)

Runs every handler now, in connection order. A handler may disconnect any connection during the fire.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
damaged:Fire(10)

Signal:FireDeferred

Signal:FireDeferred(...: T...)

Runs the handlers at the next resumption point, through task.defer, so the caller returns first.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
damaged:FireDeferred(10)

Signal:DisconnectAll

Signal:DisconnectAll()

Drops every connection. The signal stays usable.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
damaged:DisconnectAll()

Signal:Destroy

Signal:Destroy()

Disconnects everything and marks the signal dead, which is what delete calls.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
delete damaged

Signal:connect

Signal:connect(handler: (T...) -> ()): SignalConnection

The snake_case twin of Connect. Both name one function, for a file that keeps to Alloy's own naming.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
local conn = damaged:connect(function(amount) print(amount) end)
conn:disconnect()

Signal:once

Signal:once(handler: (T...) -> ()): SignalConnection

The snake_case twin of Once.

import { Signal } from "@alloy/std/signal"

local ready = new Signal<<>>()
ready:once(function() print("go") end)

Signal:wait

Signal:wait(timeout: number?): T...

The snake_case twin of Wait.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
print(damaged:wait(5))

Signal:fire

Signal:fire(...: T...)

The snake_case twin of Fire.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
damaged:fire(10)

Signal:fire_deferred

Signal:fire_deferred(...: T...)

The snake_case twin of FireDeferred.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
damaged:fire_deferred(10)

Signal:disconnect_all

Signal:disconnect_all()

The snake_case twin of DisconnectAll.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
damaged:disconnect_all()

Signal:destroy

Signal:destroy()

The snake_case twin of Destroy.

import { Signal } from "@alloy/std/signal"

local damaged = new Signal<<number>>()
damaged:destroy()