How to wait for a function return?

----------- Main
while true do  -- server cannot detect .Ended()
	changeSong() -- Set first song
	if songLength ~= nil then
		wait(songLength) -- server cannot detect .Ended()
		sound:Destroy() -- garbage collection
	end
end

I currently have this segment of code, and I want to wait until changeSong() returns a boolean to proceed to the next lines. Sort of like tween.Completed:wait(). I could have some sort of wait/repeat until loop, but that would slow down the thread and create lag, perhaps with unknown consequences.

I have a feeling coroutines may solve this, however I’m inexperienced in them and a better method might be revealed by posting.

3 Likes

The problem is that changeSong() is fired multiple times in the while loop.

while true do  -- server cannot detect .Ended()
	if changeSong() then
		wait(songLength) -- server cannot detect .Ended()
		sound:Destroy() -- garbage collection	
	end
end

Something like this has the same issue. I want to have something that will pause the program until true is returned. Not sure if it’s good advice in this case, but the reason I don’t want to use a repeat until loop is from Avoiding wait() and why. Maybe this is an exception

while true do 
changeSong()

if changeSong == false then

elseif

if songLength ~= nil then

return 

until(songLength).Value > 5 --example number 

wait(1)

if songLength == nil then

Sound:Destroy()

end
end
end

as I’m not too experienced in the area your asking for I’m not too sure this will work if it doesn’t could you please post the output here?

thanks,
X

Only events such as tween.Completed really run asynchronously (without extra work)
Calling the function will wait until it returns already. If changeSong has a wait(10) in it, then it will be at least 10 seconds before if songLength... runs.
If you want it to run at the same time and not wait to finish, use coroutines or spawn.
spawn(changeSong)

2 Likes

Coroutines would not solve it. Your current code already solved the issue.

If you want to use the Boolean result, simply set a variable to the output,

yourBool = changeSong()

Code after this line will be executed after changeSong has completed.

I suspect you might be trapped in an XY problem where your actual issue is songLength not being defined or never updating to the new song, or some other similar issue.

3 Likes

With something like that, Found a song successfully! is printed multiple times when it’s expected to only once. I probably should have provided more of the script to better convey what I was having trouble with:

local songID -- Global
local sound -- Global
local songLength -- Global
local function changeSong()
	local randIndex = randFromTable(music)
	songID = music[randIndex]
	
	sound = Instance.new('Sound', workspace) -- global for signals, garbage collection
	sound.SoundId = 'rbxassetid://' .. tostring(songID)
	sound.Name = "globalSound"
	sound.Looped = false
	sound.Volume = 0.3
	songLength = sound.TimeLength -- global for end detection
	
	local assets = {sound}
	contentProvider:PreloadAsync( assets )
	
	if checkCopyRight(songID) then
		event:FireAllClients(sound) -- send as the audio changes, because client can't detect change on server objects very well
		sound:Play()
		print("\tFound a song successfully!")
		return true
	else
		print("Recursing to find new song...")
		changeSong() -- recursive
	end
	
	
end


----------- Main
while true do  -- server cannot detect .Ended()
	if changeSong() then
		wait(songLength) -- server cannot detect .Ended()
		sound:Destroy() -- garbage collection	
	end
end

Perhaps due to the recursive part. You probably want to return the result of the recursive call, rather than returning nothing which would cause the loop to instantly run again and call the changeSong function again despite the recursive part.

Something like

else
    print("Recursing to find new song...")
    return changeSong()
end

May fix the issue.

Another cause may be that TimeLength isn’t instantly updated as sounds take time to load over the network, so you’re setting the songLength to be zero, so your loop doesn’t wait, destroys the sound, and calls the function again. This cycle stops when you load a cached sound where there is no delay is determining the length.

2 Likes

Thank you. Moving the timelength instantiation to be after the preload worked along with returning the function.

3 Likes