How to have 2 modules require each other?

If I have a module require this data module:

local dataManager = require(script.DataManager)

and then inside the data module, require the module that is calling it, the scripts break.

What’s basically happening, is I’m trying to be able to access the players data table from any module. So for any module to access and change data, they need to require the DataModule. But if the DataModule needs to require them as well, they become broken.

A better example being say this:

function dataManager:SaveData(player)
	if not plots:FindFirstChild(player.Name) then return end
	
	savePlot:Save(player) -- A saving module
	
	playerDataStore:SetAsync(player.UserId, self.PlayerData[player.UserId])
	
	clearPlot:Clear(player)
end

But then the saving module needs to require the data module again to save stuff:

local user = dataManager.PlayerData[player.UserId] -- required earlier on the script
	if not user then return end
	
	user.Items = playerItems
2 Likes

Require both modules in a script, pass the second module to the first one via a function like “Setup” and vise-versa. Or call module #1’s setup function from module #2 passing along module #2. Don’t require them in the stack, keep the variables set to nil til after the setup functions have been called. Once that happened you can use both modules. That’s how I do it for my framework.

Idk if I explained it well enough, if not I’ll provide examples.

Examples would be great :sweat_smile:

Script:

local module1 = require(Path.To.Module1)
local module2 = require(Path.To.Module2)

module1:Setup(module2)
module2:Setup(module1)

Module1:

local Module1 = {}
local module2 = nil

function Module1:Setup(module2Instance)
    module2 = module2Instance
end

return Module1

Module2:

local Module2 = {}
local module1 = nil

function Module2:Setup(module1Instance)
    module1 = module1Instance
end

return Module2

Basically, something similar to this.

You should look at Aeroframework made by @Crazyman32 it links modules from the client and the server together, etc…

Of course this would be more of a long term solution as well as a difficult one to implement, but looking at the source he uses could always help you.

Metatables for something like this would work wonders, as seen by Crazyman’s framework. I’m sure he could of more assistance with this then me however :laughing:

For my modules i usually have a function called init (initialization), and it doesnt conflict that way.

example

-- module 1

local module2 = false
local module = {}

function module.init()
    module2 = require(module2.location)
end

return module

-- module 2
local module1 = false
local module = {}

function module.init()
    module1 = require(module1.location)
end

return module

-- The main script
local module1 = require(module1.location)
local module2 = require(module2.location)

module1.init()
module2.init()

Yeah, that’s pretty similar to what I replied with. Only thing is, you’re creating two instances of each module instead of passing on the existing instances from the script you called “init” in.

For your information, this method is called ‘lazy loading’ and in some cases it is faster to use modules this method, generally when you want to run the module at a later point, rather than immediatley (as you are meant to be removing all yielding)

No need to do init functions and stuff like others have suggested, you just need to use metatables. Take a look at my response here

https://devforum.roblox.com/t/how-did-you-organize-your-games-framework-show-us/230000/6

5 Likes