How do you stop a function early?

If you are going to say I should use return or break, that does not solve the problem.
I’m trying to make a function stop when an event is fired.

Please see example of what I mean below.

-- This function will run forever when called
function printTest()
    while wait() do
        print("Hi")
    end
end

printTest()

BindableEvent.Event:Connect(function()
  -- How do I make it so that the function can stop printing??
end)

Also I considered using if statements, but it won’t really look nice and is going to be hard to maintain when the function is really long. So any suggestions on how I could stop a function easily?

Threads can’t stop other threads. Threads have to stop themselves.

So keep an external variable that your loop looks at, and the event changes:

local stopped = false

event:Connect(function() stopped = true end)

while not stopped do
  print("Hi")
  wait()
end

Like I said, it’s handy when the function is simple like you provided.
Now how about the one below:

local matchCreationLoadingAnimation = coroutine.create(function()
		local currentTimestamp = os.time()
		repeat 
			wait(0.5)
			createFrame.LoadingFrame.LoadingText.Text = randomLoadingPhrases[math.random(1, #randomLoadingPhrases)]
		until 
			currentTimestamp + clientConfigs.MatchCreationLoadingTime <= os.time() or loadingAnimationOverride

		if loadingAnimationOverride then
			loadingAnimationOverride = false

		else
			currentTimestamp = os.time()
			repeat wait() until currentTimestamp + 4 <= os.time() or loadingAnimationOverride 
			createFrame.LoadingFrame.LoadingText.Text = "Error: Match creation failed..."
			wait(3)
			createFrame.LoadingFrame:TweenPosition(UDim2.new(0, 0, 1, 0), Enum.EasingDirection.In, Enum.EasingStyle.Quad, 0.5)
		end
	end)

How am I able to stop this coroutine without having to use the override bool value because the code already looks messy. Not to mention, I’m going to add more stuff to this function, so more things could go wrong.

A systematic way of doing this would be to use a promise which provides support for this sort of thing. Perhaps you should look further into it and see what ideas you can come up with.

1 Like

The ability to cancel at any time in the middle of an operation is a huge requirement that has a lot of side effects.

It will require a lot of manual labor, because you need to think about exactly what happens if the thread is cancelled at any point. Sometimes, you don’t want to just get yoinked out of the loop without any warning: maybe you want to wait until the next “good spot” to cancel instead.

Promises, which @dthecoolest mentioned, can certainly help you organize what happens when your function cancels, but they don’t remove the work—you’ll still need to implement all those the onCancel functions.

1 Like

you can try using a thing called coroutine

That’s what I already used as you can see in my latest reply. Please read carefully and try to understand the problem before you just type out random stuff. If you still think coroutine is the way to go, please explain how exactly.

1 Like

Does this solve your issue?

local function printTest()
  local runLoop = true

  coroutine.wrap(function()
    while runLoop do
      task.wait()
      print("Hello World!")
    end
  end)()

  return function()
    runLoop = false
  end
end

local stopLoop = printTest()

BindableEvent.Event:Connect(stopLoop)

This is definitely not the best way of doing this, it’s easier to use a promise based library or smth.

1 Like