Basic Signal V1
I came up with a module that will help you in OOP Coding A simple and useful module compared to its alternatives
This is an oop example prepared to explain the use of the BasicSignal Module:
--!strict
local Signal = {}
Signal.__index = Signal
local Connection = {}
Connection.__index = Connection
export type Connection = {
index : number,
signal : Signal,
Disconnect : (Connection) -> ()
}
export type Signal = {
Connections : {[number] : (any) -> ()},
Fire : (Signal, any) -> (),
Connect : (Signal, callBack : (any) -> ()) -> Connection,
Once : (Signal, callBack : (any) -> ()) -> (),
Wait : (Signal, timeout : number) -> (),
}
function Signal:Fire(...)
for i, v in pairs(self.Connections) do
v(...)
end
end
function Signal:Connect(callBack : (any) -> ()) : Connection
table.insert(self.Connections, callBack)
local index : number? = table.find(self.Connections, callBack)
return setmetatable({
index = index,
signal = self :: Signal
}, Connection) :: any
end
function Signal:Once(callBack : (any) -> ())
local connection
connection = self:Connect(function(...)
callBack(...)
connection:Disconnect()
end)
end
function Signal:Wait()
local thread = coroutine.running()
self:Once(function(...)
coroutine.resume(thread, ...)
end)
return coroutine.yield(thread)
end
function Connection:Disconnect()
table.remove(self.signal.Connections, self.index)
end
return function() : Signal
return setmetatable({
Connections = {}
}, Signal) :: any
end
I noticed your :Wait() doesn’t use coroutine.resume and coroutine.yield which would be more efficient and less bloated. So I made one of my own using them if you’d like to take the :Wait() code for your own aswell.
--!strict
--> Signal Class
local Signal = {}
Signal.__index = Signal
--> Connection Class
local Connection = {}
Connection.__index = Connection
--> Types
export type Connection = {
index : number,
signal : Signal,
Disconnect : (Connection) -> ()
}
export type Signal = {
Connections : {[number] : (any) -> ()},
Fire : (Signal, any) -> (),
Connect : (Signal, callBack : (any) -> ()) -> Connection,
Once : (Signal, callBack : (any) -> ()) -> (),
Wait : (Signal, timeout : number) -> (),
}
--> Signal Methods
function Signal:Fire(...)
for i, v in pairs(self.Connections) do
v(...)
end
end
function Signal:Connect(callBack : (any) -> ()) : Connection
table.insert(self.Connections, callBack)
local index : number? = table.find(self.Connections, callBack)
return setmetatable({
index = index,
signal = self :: Signal
}, Connection) :: any
end
function Signal:Once(callBack : (any) -> ())
local connection
connection = self:Connect(function(...)
callBack(...)
connection:Disconnect()
end)
end
function Signal:Wait()
local thread = coroutine.running()
self:Once(function(...)
coroutine.resume(thread, ...)
end)
return coroutine.yield(thread)
end
--> Connection Methods
function Connection:Disconnect()
table.remove(self.signal.Connections, self.index)
end
--> return
return function() : Signal
return setmetatable({
Connections = {}
}, Signal) :: any
end
Also, here’s an example of usage:
local signal = require(game:GetService('ReplicatedStorage').signal)
local testSignal = signal()
local testConnection = testSignal:Connect(function(number : number)
print(number)
end)
testSignal:Once(function(number : number) --> prints '5' once
print(number)
end)
testSignal:Fire(5) --> prints '5'
task.wait(5)
testConnection:Disconnect()
testSignal:Fire(10) --> doesn't print