Categories
Blog

Simple Coroutine Style Yields in JavaScript/TypeScript

Hey Folks!

If you are like me you have likely spent most of your time in a coding language that is not JavaScript (JS) or TypeScript (TS). Maybe you come from the beautifully brilliant world of C#. If you do then you’ve likely got an understanding of the gorgeous simplicity and power of a coroutine.

As a refresher or perhaps a primer, what is a coroutine? Put at its simplest a coroutine is an asynchronous function. They allow you to multitask instead of simply completing each function in a sequence. If you were hoping for anything more technical than this I don’t think I’m the person to turn to.

So you’ve jumped into JS then and you find yourself really needing a waitForSeconds style function like you’ve been using in Unity or the equivalent in Unreal.

You are probably thinking at this point:

Technically they don’t exist. But you don’t need to jump out a window quite yet.

It turns out there is a system that’ll achieve this goal and it is known as “Promises”. If you’d like to go down a path of suffering I suggest you google JavaScript Promises and try to find an example that is human readable.

I’m unclear why but apparently it is illegal to make something that is easy to understand and even easier to implement. Everyone has nested brackets or otherwise hideous loops that take a phenomenal amount of time to grasp.

And don’t even get me started on all the thens and catches. I get that eventually you will want to know these things but come on folks. For game development most of that fluff is just not helpful.

Now that I’ve given you an appropriately long intro akin to a baking recipe blog, I’ll drop the easy out!

First place the code below outside of your class, for convenience I’d suggest placing it above the class.

export function waitforseconds(seconds: number): Promise<void>
{
    return new Promise<void>(resolve =>
    {
        setTimeout(() => { resolve(); }, seconds * 1000);
    });
}

Once that is done you can now add “waitforseconds” awaits in any async function as shown here:

    async codeExample() : Promise<void>
    {           
        for (var i = 0; i < 5; i++)
        {
            cc.log("You'd put any code you wanted to happen before the next iteration here.");
            await waitforseconds(1.1); //And this will wait for 1.1 seconds.
        }
    }

You’ll notice two major differences to this logic over other in class functions. Firstly it starts with “async” before the function name. This is mandatory to make “await” work. Next we have the function type of “Promise<void>”. In this case that is because we aren’t returning anything.

And that’s it! Turns out the above code works both for TypeScript and JavaScript without any formatting changes.

It is worth noting that if you aren’t sure how to call the above codeExample you can do so like you would any other function. A simple “this.codeExample();” will work brilliantly.

You can use as many awaits as you want in just about any place you want. The function will wait for the duration to pass before it continues on with the logic but it will not hang your program while it does so.

If the function you are making needs to be universal like the await itself (or is just not class specific) you simply need to add “function” after “async” and it’ll work.

See how easy this was? No PHD in hieroglyphics needed. At worst the actual promise itself is a bit hideous but you don’t need to read it beyond grasping the basic fundamentals. It waits x seconds and then releases the asynchronous function to continue.

Finally, feel free to rename it “waitForSeconds”. I’ve been meaning to do that but honestly at a certain point you just shrug and say “You are the monster I created and I love you.”

[If you like this or have any questions feel free to ping me @oafkad on twitter.]