Create wait function by passing resolve to setTimeout

Placing the resolve function of a Promise inside a setTimeout function, and then awaiting that Promise, effectively creates a wait or sleep mechanism in JavaScript. This is due to the interplay of Promises, setTimeout, and the async/await syntax.

Here's a breakdown:

  • Promises for Asynchronous Operations:

    A Promise represents the eventual completion (or failure) of an asynchronous operation and its resulting value. It has three states: pending, fulfilled (resolved), or rejected.

  • setTimeout for Delayed Execution:

    setTimeout is a Web API function that schedules a function to be executed after a specified delay. It's inherently asynchronous; it doesn't block the main thread while waiting.

  • Connecting resolve and setTimeout:

    When you create a Promise and place setTimeout(resolve, delay) within its executor function, you're essentially saying: "This Promise will remain pending until the setTimeout finishes its delay and then calls the resolve function." Calling resolve transitions the Promise from pending to fulfilled.

  • async/await for Synchronous-like Flow:

    The async/await syntax allows you to write asynchronous code that appears synchronous. When you await a Promise, the execution of the async function pauses at that line until the Promise resolves.

How it creates a wait

Consider this common pattern:

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function myFunction() {
    console.log("Starting...");
    await delay(2000); // This line pauses execution for 2 seconds  
    console.log("After 2 seconds...");
}
myFunction();

In this example:

  • delay(2000) returns a Promise.
  • Inside that Promise, setTimeout(resolve, 2000) is called. This means the resolve function of the Promise will be called after 2000 milliseconds.
  • When myFunction calls await delay(2000), the async function pauses its execution.
  • The JavaScript event loop continues processing other tasks, but myFunction remains paused until the delay Promise resolves (which happens when setTimeout calls resolve).
  • Once resolve is called, the delay Promise is fulfilled, and myFunction resumes execution from the await line.

This combination effectively creates a wait or sleep behavior because the async function's execution is halted until the Promise that's tied to the setTimeout resolves, signifying the completion of the desired delay.

Expand codes to view full details

// Customize resolve function.
//  Replace resolve with () => {}.
//  It means from top level Promise, it is passing resolve() to setTimeout().
//  setTimeout() is executing a callback function that happens to be an anonymous function.
//  That anonymous function is executing the resolve().
function delay(ms) {
    return new Promise(resolve => setTimeout( () => { resolve("I'm done") } , ms));
}
async function myFunction() {
    console.log("Starting...");
    const result = await delay(2000); // This line pauses execution for 2 seconds  
    console.log(result); // Logs "I'm done" after 2 seconds
    console.log("After 2 seconds...");
}
myFunction();

/* OUTPUT:

Starting...
I'm done
After 2 seconds...

*/