How to yield until a ModuleScript returns a value?

I’ve adopted the Madwork framework of writing code. I have a ModuleScript called Madwork which contains useful ModuleScripts for my game. Madwork returns the table Madwork as well as assigning _G.Madwork = Madwork, so that any Script/LocalScript can do things like this at the top of the code:

local Madwork = _G.Madwork -- Framework saved in Global table
local Promise = require(Madwork.GetShared("Promise") -- Easy require

The problem is that asynchronous functions within _G.Madwork like :WaitForChild(module_path) mean that other scripts try to index _G.Madwork before it has even been assigned. I have to do something like:

wait(5) <-- Wait for ModuleScripts to load e.g. ReplicatedStorage.Promise
local Madwork = _G.Madwork <-- Framework saved in Global table
local Promise = require(Madwork.GetShared("Promise") <-- Easy require

Otherwise I will be assigning the Madwork variable before the ModuleScript has even returned anything:

local Madwork = nil -- Not good

Is there a clever way to ensure that when I assign:

local Madwork = _G.Madwork

That it actually already exists in the first place, otherwise yield the script?


As of writing this post, this has fixed it for me:

repeat task.wait() until _G.Madwork ~= nil
local Madwork = _G.Madwork

Is there still an easier and neater way?

If you absolutely need to use _G for this, then I don’t believe you can get much neater than repeatedly waiting until it exists.

You could hackily get it by giving _G a metatable if you don’t want to wait until the task.wait call finishes

local thisThread = coroutine.running()

setmetatable(_G, getmetatable(_G) or { __newindex = function(self, k, v)
    rawset(self, k, v)

    if k == 'Madwork' and coroutine.status(thisThread) == 'suspended' then
        task.spawn(thisThread, v)
    end
end})

local madwork = _G.Madwork or coroutine.yield()

You could also add the current thread to a big table inside of _G and resume the threads once _G.Madwork finishes running. But realistically if you’re looking for cleanliness I think the absolute neatest way to go about it would be to just have a single big require call at the top of each script needing to access the framework.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.