In the forum I read that the Promise module has a method called delay that is a more efficient replacement of wait(). So, I decided to isolate that method and turn it into a module that doesn’t depend on promises. After many attempts I could do it.
Here is the module.
-- the initial node in the linked list
local first
local connection
function delay(seconds, resolve)
assert(type(seconds) == "number", "Bad argument #1 to Promise.delay, must be a number.")
-- If seconds is -INF, INF, NaN, or less than 1 / 60, assume seconds is 1 / 60.
-- This mirrors the behavior of wait()
if not (seconds >= 1 / 60) or seconds == math.huge then
seconds = 1 / 60
end
local startTime = os.clock()
local endTime = startTime + seconds
local node = {
resolve = resolve,
startTime = startTime,
endTime = endTime,
}
if connection == nil then -- first is nil when connection is nil
first = node
connection = game:GetService("RunService").Heartbeat:Connect(function()
local threadStart = os.clock()
while first ~= nil and first.endTime < threadStart do
local current = first
first = current.next
if first == nil then
connection:Disconnect()
connection = nil
else
first.previous = nil
end
current.resolve(os.clock() - current.startTime)
end
end)
else -- first is non-nil
if first.endTime < endTime then -- if `node` should be placed after `first`
-- we will insert `node` between `current` and `next`
-- (i.e. after `current` if `next` is nil)
local current = first
local next = current.next
while next ~= nil and next.endTime < endTime do
current = next
next = current.next
end
-- `current` must be non-nil, but `next` could be `nil` (i.e. last item in list)
current.next = node
node.previous = current
if next ~= nil then
node.next = next
next.previous = node
end
else
-- set `node` to `first`
node.next = first
first.previous = node
first = node
end
end
return
end
return delay
Here is an example of how it is used.
local delay = require(game:GetService("ServerScriptService").DelayModule)
print("Start")
delay(5, function ()
print('OK') -- prints after 5 seconds.
end)
The problem is that, even though it works well, I can’t understand how it works. I refer to this part of the code:
else -- first is non-nil
if first.endTime < endTime then -- if `node` should be placed after `first`
-- we will insert `node` between `current` and `next`
-- (i.e. after `current` if `next` is nil)
local current = first
local next = current.next
while next ~= nil and next.endTime < endTime do
current = next
next = current.next
end
-- `current` must be non-nil, but `next` could be `nil` (i.e. last item in list)
current.next = node
node.previous = current
if next ~= nil then
node.next = next
next.previous = node
end
else
-- set `node` to `first`
node.next = first
first.previous = node
first = node
end
end
Please, could someone help me to understand this code.