2

# [SOLVED] How to run a function once in Object-Oriented Programming?

Edited 3 months ago

Hello. I'm trying to make my own Custom Signal module without using BindableEvents nor using a module from the DevForum. But I don't know how to make the handler Signal:Once() which basically uses Connect but only does it once. I tried using coroutines, debounce, and setting the function to nil, but it still runs more than once like Signal:Connect() and not like RBXScriptSignal:Once(). Here's the module for reference:

local module = {}
module.__index = module

local backupBindableEvent = Instance.new("BindableEvent")

function module.new(signalName: string)
local self = setmetatable({}, module)
local newSignal = {}

local newSignalName: string

if signalName ~= nil then
newSignalName = signalName
else
newSignalName = "Event"
end

self._listeners = require(script.Listeners).new()
local listenersModule = self._listeners

function newSignal:Connect(func)

return {
Connected = true,
Disconnect = function(self)
listenersModule:RemoveListener(func)
self.Connected = false
end
}
end

function newSignal:ConnectParallel(func)
return {
Connected = true,
Disconnect = function(self)
listenersModule:RemoveListener(func)
self.Connected = false
end
}
end

function newSignal:Once(func)
return backupBindableEvent.Event:Once(func) -- using BindableEvents until i figured it out!
end

function newSignal:Wait()
return backupBindableEvent.Event:Wait() -- using BindableEvents until i figured it out!
end

self[newSignalName] = newSignal

return self
end

function module:Fire(...: any)
local paramsTable = table.pack(...)

backupBindableEvent:Fire(table.unpack(paramsTable))

local listenersModule = self._listeners

repeat task.wait() until listenersModule:GetListenersAsync() ~= nil
local listenersTable = listenersModule:GetListenersAsync()

if listenersTable ~= nil then
for _, listenerFunc in pairs(listenersTable) do
listenerFunc(table.unpack(paramsTable))
end)
end
end
end)
end

return module


Also I don't know how to make the Signal:Wait() function. Right now, I'm temporarily using BindableEvents to make those functions work.

And also, if you noticed anything wrong in my module that is off-topic, lemme know!

0
Wait will be almost the same as :Once but at the end instead of returning, do a repeat wait() until not myTable.Connected blowup999 659 — 7mo

0
blowup999 659
7 months ago

It's hard to help here because this is highly dependent on the listenersModule you have - Personally, I would add an :AddOnce(func) in addition to :AddListener(func) and let that module handle it, but this also runs into the issue of the Connected variable being different from reality.

Easiest way with given code is:

function newSignal:Once(func)
local myTable = {Connected = true}
local function singleUse()
myTable:Disconnect()
func()
end
function myTable:Disconnect()
listenersModule:RemoveListener(singleUse)
myTable.Connected = false
end
return myTable
end

0
The listenersModule has 3 functions: :AddListener(), :RemoveListener(), and :GetListenersAsync(). The listenersModule just simply creates an array of functions T3_MasterGamer 2127 — 7mo
0
I also need help in making the :Wait() function. Thanks! T3_MasterGamer 2127 — 7mo
0
But sure, I’ll try to make an :AddOnce() function. T3_MasterGamer 2127 — 7mo
0
Sadly, yours did not work but I finally solved the :Once() function. I just converted the listener to a thread, and closed it once it was fired to avoid of doing it again. T3_MasterGamer 2127 — 7mo