A question about Knit

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?

2 Likes

Knit has a couple neat methods in it.

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

1 Like

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:

  1. When requiring the module that contains this code, put the require within the Knit.OnStart() method

  2. Require these modules only after Knit loads, you would need to ensure that you properly implement your load order to do this.

1 Like

Thank you so much! U r right! It’s not efficiently possible in Roblox.

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
4 Likes

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.

2 Likes