Measure Asynchronous Function and Delay by X Seconds with SetTimeout in JavaScript

Last Updated:
Measure Asynchronous Function and Delay by X Seconds with SetTimeout in JavaScript

The title of this post is a bit long, but for a valid reason. It was impossible to sum up in fewer words!

I was recently working on a piece of functionality within a React project. It needed a minimum delay on an asynchronous function in order to show a full loop of an animation. The animation was a 2 second loop.

The specification was that an API request was to be made, and the time taken to complete was removed from the 2 seconds. This means that if the API request is returned in under 2 seconds (for example 500ms), and we must wait another 1500ms. The image below shows the perfect outcome.

An animation starts at 0 seconds. The async function resolves in 0.5 seconds, and the settimeout runs for 1.5 seconds. The animation stops at 2 seconds.

However, in the scenario that the request was not returned within 2 seconds, the animation would continue until the request resolved.

In the below example the request is returned in 2.5 seconds, and the animation is stopped as soon as the request is completed.

An animation starts at 0 seconds. The async function resolves in 2.5 seconds, The animation stops at 2.5 seconds.

If the asynchronous  function runs for exactly 2 seconds then no additional JS delay is needed and the animation should stop immediately.

An animation starts at 0 seconds. The async function resolves in 2 seconds, The animation stops at 2 seconds.

I knew I needed some form of JavaScript wait function. I did not want to use an await on the callback function, and then wait for 2 seconds, as this is forcing the user to wait longer than required.

An animation starts at 0 seconds. The async function resolves in 0.5 seconds. The <code>SetTimeout</code> runs for 2 seconds. The animation stops at 2.5 seconds.

I need a solution that would time the asynchronous function, and measure how much time was left out of the 2 seconds. Then use a SetTimeout function to delay/sleep the code.

Solution

The solution was to create a piece of code that would measure the execution time for a section of code in JavaScript. It times the asynchronous function, then waits for x seconds. In a nutshell: Delay code for specific time, including await time.

The Helper Function

export const delayAwait = async (start, minDelay) => {
    return new Promise((resolve) => {
        const timePassed = Date.now() - start;
        const timeToWait = minDelay - timePassed;
        if (timeToWait < 0) {
            resolve(true);
        }
        setTimeout(() => {
            resolve(true);
        }, timeToWait);
    });
};

How To Use

The function is then used as shown below.

// Get a timestamp of before the request is triggered.
const startTime = Date.now();

// Set the total time to wait in milliseconds.
const totalTimeToWait = 2000;

// Start the animation.
startAnimation();

// Trigger the async function, and wait using an await.
await yourAsyncFunctionHere()

// Once async function is resolved, pass the timestamp to the delay helper function.
// Also pass in the total time to wait.
await delayAwait(startTime, 2000);

// Once the timer has finished, stop animation.
finishAnimation()

Hopefully this helps! You can find me on Twitter if you have any questions.

Related Posts