What do synchronous and asynchronous mean in scripting context?

I am trying to understand what these 2 terms mean, I kept seeing terms like “synchronous functions” and “asynchronous functions” but I can’t understand what does it mean despite searching it up. Can anyone give me a brief and concise explanation along with practical examples so I can understand better?

3 Likes

In Roblox scripting, synchronous code is code that runs in a linear, step-by-step manner. The script will execute each line of code in order, one after the other, and will not move on to the next line until the current line has completed execution.

Asynchronous code, on the other hand, allows multiple lines of code to run simultaneously or “in the background.” This allows a script to perform multiple tasks at the same time, rather than waiting for one task to complete before moving on to the next. Asynchronous code is useful for tasks that may take a while to complete, such as loading data from a server or waiting for user input.

For example, the wait() function in Roblox is a synchronous function that stops the execution of the script for a specified amount of time, and in contrast, the spawn() function allows to run a function asynchronously in the background.

12 Likes

Thanks for the enlightment, is it possible for you to give some practical examples where I need to use synchronous/asynchronous logic in certain scripting contexts?

1 Like

The best example I can give is lets say you have a script here:

function countTo10()
 for I = 1, 10, 1 do 
   wait(1) 
   print(I)
 end 
end

function executeDone()
 print("Done")
end

if you execute this code, you must call the functions in order to get the result you are expecting:

countTo10()
executeDone()

will give you the output of:

1 
2
3
4
5
6
7
8
9
10
Done

These are two synchronous functions, because by default lua will go in order. You can specifiy if you want to make a function asynchronous though, like so:

function countTo10()
 coroutine.wrap(function() --creates and runs a function on a separate thread 
   for I = 1, 10, 1 do --creates a loop that counts from 1 to 10
     wait(1) 
     print(I)
   end
 end)
end

What this does is creates a coroutine, which will run the provided function as a separate “thread” allowing it to run without interfering with the master thread that runs down the list in your script. This means that when you run your two functions in the same order now, the output will look like this:

1
Done
2
3
4
5
6
7
8
9
10

Why is this? Well lua looks at your script and fires the first function, which starts counting to 10 immediately, but since it’s run on a separate thread, it is allowed to continue onto the next function which says that you’re done, even though you’re not. Obviously you would want to keep this script synchronous, but there are scenarios in which you would like asynchronous functions to occur simultaneously:

Lets say you wanted to decrease a player’s health every 5 seconds in a script that you may need to continue onto further logic before the player is dead:

function reducePlayerHealth(Humanoid, increments, minimum)
  coroutine.wrap(function() --creates and runs a function on a separate thread 
   for I = Humanoid.Health, minimum, -increments do 
    Humanoid.Health = I
    wait(5)
   end
  end)
end

reducePlayerHealth(plrHumanoid, 10, 50)

If you did not include the coroutine in there, your entire script would actually wait 25 seconds before executing code after you run the function. This may or may not be what you intend the script to do, so really whether you use synchronous function or asynchronous you will really only be able to know on your own when you need to. Any time there are multiple things happening, especially with wait times, you generally are probably going to use asynchronous functions, which I would honestly looks into coroutines which are probably the easiest to understand.

9 Likes
  • Synchronous logic:

    • You want to play a sound effect and then immediately play a animation for the player character. Since the sound effect and animation are related, you would use synchronous logic to ensure that the sound effect plays before the animation starts.
    • You want to check if a player’s health is below a certain threshold and, if so, display a message and then end the game. You would use synchronous logic to ensure that the message is displayed before the game ends.
  • Asynchronous logic:

    • You want to load data from a remote server and then use that data to create objects in the game. Since loading data from a server can take some time, you would use asynchronous logic so that the game can continue to run while the data is being loaded, rather than freezing.
    • You want to wait for a player’s input before proceeding with the next step in the game. Since waiting for user input can take an indeterminate amount of time, you would use asynchronous logic so that the game can continue to run while waiting for the input.
4 Likes

I am quite new to coroutines after a long hiatus. Can you introduce me any tutorials to get started learning it? Is there anything else that are similar to coroutines as well?

click this link to go to roblox’s documentation on coroutines. But honestly all I’ve ever done with coroutines is use them as I would the now deprecated spawn() function or not deprecated task.spawn in which you’re simply creating a separate thread right then and there, then running it. Of course I recommend using coroutines since roblox recommends it, but honestly they all do something of the same thing. There are slight performance variations but depending on your use case it might be irrelevant.

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.