Serialising Async Functions

How to create a serialised async function in Javascript / Typescript.

So it turns out that I am way less versed in Javascript packages than I thought that I was, and didn't realise that Async existed...

So instead of using their queue function I created my own.

I needed to create a helper which would ensure that a function would only execute one-at-a-time to assist with time ordering of changes emitted by the my editor. Changes are sorted server-side when saved to the database but this can only help live-subscribers if delivery is queued so that there is actually something to sort.

After all that, I published a wrapper which serialised my function (plus a bunch of other stuff, like data transforms), and wanted to share it with anyone who might benefit 🙂

An extended version of the below can be found at Async Function Serializer, but this was the core code!

type Queue<InputType, ResultType> = {
    resolve: ( data: ResultType ) => void,
    input: InputType,
}[]

function serialise<InputType, ResultType>( 
    functionToSerialise: ( input: InputType ) => ResultType, 
): ( input: InputType ) => Promise<ResultType> {

    const queue: Queue<InputType, ResultType> = [];
    let isRunning = false;

    async function run () {
        isRunning = true;

        const current = queue.shift();
        if ( current ) {
            const result = await functionToSerialise( current.input );
            current.resolve( result );
        }
        
        if ( queue.length ) await run();
        else isRunning = false;
    }

    return async function ( input: InputType ): Promise<ResultType> {
        return await new Promise<ResultType>( resolve => {
            queue.push({ resolve, input });
            if ( !isRunning ) run();
        });
    }; 
}

Written: 19 December 2021