Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

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

Asked by 1 year ago
Edited 1 year 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)
        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!

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 — 1y

1 answer

Log in to vote
0
Answered by
blowup999 659 Moderation Voter
1 year 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
    listenersModule:AddListener(singleUse)
    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 2189 — 1y
0
I also need help in making the :Wait() function. Thanks! T3_MasterGamer 2189 — 1y
0
But sure, I’ll try to make an :AddOnce() function. T3_MasterGamer 2189 — 1y
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 2189 — 1y
Ad

Answer this question