✓ Accepted answer
You can create counter, every time you spawn something, increase the counter by 1, at the end of the function, decrease the counter back by 1, this means counter won't be 0 while at least single thread is active, then you can repeatedly wait until counter ain't 0:
local count = 0
while true do
for i,v in ipairs(DataStorePages:GetCurrentPage()) do
spawn(function()
count += 1
local BlockData
local success2, errorMessage2
success2, errorMessage2 = pcall(function()
BlockData = BlocksDatastore:GetAsync(v.key)
end)
if success2 then
LoadBlock(BlockData)
else
table.insert(FailedDataCache, v.key)
end
count -= 1
end)
end
if DataStorePages.IsFinished == false then
DataStorePages:AdvanceToNextPageAsync()
else
break
end
end
while count ~= 0 do
task.wait()
end
Loaded.Value = true
However if i leave the while not something do task.wait() end is non-professional, the code won't just wait once, it will repeatedly wait every frame, of course you won't see performance difference but who cares, other simple way better than this is by using BindableEvent:
local finished = Instance.new("BindableEvent")
local count = 0
while true do
for i,v in ipairs(DataStorePages:GetCurrentPage()) do
spawn(function()
count += 1
local BlockData
local success2, errorMessage2
success2, errorMessage2 = pcall(function()
BlockData = BlocksDatastore:GetAsync(v.key)
end)
if success2 then
LoadBlock(BlockData)
else
table.insert(FailedDataCache, v.key)
end
count -= 1
finished.Event:Fire()
end)
end
if DataStorePages.IsFinished == false then
DataStorePages:AdvanceToNextPageAsync()
else
break
end
end
while count ~= 0 do
finished.Event:Wait()
end
Loaded.Value = true
That way it will only check if count isn't 0 every time finished is fired, that is every time spawn thread ends since i added the :Fire there. :Wait is a function that waits until :Fire is executed.