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) listenersModule:AddListener(func) return { Connected = true, Disconnect = function(self) listenersModule:RemoveListener(func) self.Connected = false end } end function newSignal:ConnectParallel(func) task.desynchronize() listenersModule:AddListener(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)) task.defer(function() 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 task.defer(function() 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!
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 listenersModule:AddListener(singleUse) function myTable:Disconnect() listenersModule:RemoveListener(singleUse) myTable.Connected = false end return myTable end