Recently, I started to use the Knit which is made by Sleitnick. I have a question about Knit. If u want to use the function which is inside the modules (services), u need to require the Knit, use the Knit.GetService(), and call the function which is in the service out. However, if I want to call it out, it took time for the modules to load since I have a lot of modules. Therefore, it affects the time it takes to index the table of services that Knit has. Since it affects the time, the script will print out an error and break the script. For example: (I am sorry. My English is bad. Therefore, I will try my best to explain it out using the example)
The script prints out an error and break.
local Knit = require("The place I put the Knit")
local DS = Knit.GetService("DataService")
local Data = DS:GetData(plr) -- Break
The script works fine since the modules loaded
local Knit = require("The place I put the Knit")
local DS = Knit.GetService("DataService")
task.wait(6)
local Data = DS:GetData(plr) -- Works :>
How can I avoid using the task.wait() to wait for the modules to load?
If you want to access a service from another service, you should use MyService:KnitStart() by doing
local Knit = require("Knit location")
local Service = Knit.CreateService{
Name = "Service";
Client = {};
}
function Service:KnitStart()
local DS = Knit.GetService("DataService")
local Data = DS:GetData(plr)
end
On the other hand, if you are using anything other than a Service, you need to wait for Knit to start. To do this you can use the .OnStart() method to get a promise that is resolved when Knit starts. This looks something like this:
local Knit = require("Knit location")
Knit.OnStart():andThen(function()
local DS = Knit.GetService("DataService")
local Data = DS:GetData(plr)
end):catch(warn)
All of this is available on the Knit docs/API under execution model: Execution Model | Knit
Thx for ur explanation! However, if I want to use the Data variable outside the Knit.OnStart() scope block, I need to turn Data into a global variable. Is there any way to do it without creating a new scope block?
Ideally, you should write all of your code that relies on Data within the Knit.OnStart() scope, otherwise you will run into the same problem you had earlier. This allows your code to run asynchronously without pausing the thread that required the module containing this code.
If you still need a method to synchronously yield until the data loads, you can use the :await() method available in Promises (as @verret001 pointed out). As a result, your code would look something like this:
local Data
Knit.OnStart():andThen(function()
local DS = Knit.GetService("DataService")
Data = DS:GetData(plr)
end):catch(warn):await()
-- continue code here
2 additional options that allow you to keep asynchronous code execution while also waiting for Data to load are as follows:
When requiring the module that contains this code, put the require within the Knit.OnStart() method
Require these modules only after Knit loads, you would need to ensure that you properly implement your load order to do this.
You shouldn’t have to busy-wait here? You can call :await() on a promise, and even if you couldn’t, you could use a bindable event or coroutines to yield the thread and to continue it when the data has been found.
OP wanted to have it so that the Data was accessible in the main code block, outside of the promise. I’m not sure how you would use a coroutine/bindable event to yield the main code block of a ModuleScript or even a normal Script/LocalScript, so if you could clarify what you mean by this I would appreciate it.
I was referring to your use of repeat task.wait() until Data ~= nil, and your statement that it’s not efficiently possible in roblox
This would be an example of using a bindable event
local GetData = Instance.new("BindableEvent")
Knit.OnStart():andThen(function()
local DS = Knit.GetService("DataService")
local Data = DS:GetData(plr)
GetData:Fire(Data)
end):catch(warn)
local Data = GetData.Event:Wait()
-- continue code here
Though in this case, it’d probably be optimal to just do this
local Data
Knit.OnStart():andThen(function()
local DS = Knit.GetService("DataService")
Data = DS:GetData(plr)
end):catch(warn):await()
-- continue code here
-- data will be set as await would have yielded until it was complete
Ah I see what you mean, I never considered that solution to synchronously yield a thread. I take back my prior claim that it “is not efficiently possible in Roblox”. It’s rather embarrassing that I had never considered or encountered it until now. Although I am not sure what the overhead is on this, it is no doubt better than busy waiting.
I double checked the source code for Promises and it implements this solution, so your solution is definitely most optimal here. I initially skimmed your original post and for some reason read “await” as “async”, so I had dismissed it at first, and to that end owe you an apology.
@LingBlack87661, I would take a look at this solution as it definitely solves the second question you had.