Understanding `async/await` in NodeJS/Typescript

Example of `async/await` in Typescript to demonstrate the "push back into queue" and "unpredictability of sequence"

Here is a Typescript example of evaluating, and understanding the behaviour of async/await in NodeJS.

This example, triggers multiple async calls, without waiting ( testAwait ). testAwait in turn, awaits sayHello to execute. There is some additional complexity to mimic of sayHello going one level deeper, and waiting for a timeout, for "even" triggers.

This example demonstrates the fact that an async will push the execution of the Promise into the queue at the end. So, next "scheduled" task will be executed first. Look for the sequence of 1-1-1 and figure things out for yourself.

// example 1
const logs: Array<string> = [];

// example 2
/* const logs = {
   push: console.log
} */

const TASK_COUNTER = 2 as const;
const GROUP_COUNTER = 2 as const;

function getOutputTimestamp(): string {
  return '';
  // return `${(new Date().toISOString)}: `;
}

async function sleep() {
  await setTimeout(() => {}, 1000);
}

function add(a: number, b: number) {
  return a+b
}

async function sayHello(prefix: number[], deeper: boolean ) {
  logs.push(`${getOutputTimestamp()}${prefix}: start - ${deeper? 'deep' : 'shallow'}`);
  if (deeper) {
    logs.push(`${getOutputTimestamp()}${prefix}: Deeper`)
    await sleep()
  }
  logs.push(`${getOutputTimestamp()}${prefix}: end - ${deeper? 'deep' : 'shallow'}`);
}

async function testAwait(prefix: number[]) {
  for (let i=1; i<=TASK_COUNTER; i++) {
    logs.push(`${getOutputTimestamp()}${prefix}: before ${prefix}-${i}`);
    await sayHello([...prefix, i], prefix.reduce(add,0) % 2 === 0);
    logs.push(`${getOutputTimestamp()}${prefix}: after ${prefix}-${i}`);
  }
}

async function run() {
  const promises = [];  
  for (let i=1; i<=GROUP_COUNTER; i++) {
    for(let j=1; j<=i; j++) {
      const counter = j;
      const msgPrefix = [i, counter]
      logs.push(`${getOutputTimestamp()}${msgPrefix}: trigger`);
      promises.push(testAwait(msgPrefix));
      logs.push(`${getOutputTimestamp()}${msgPrefix}: done`);
    }
  }
  return Promise.all(promises);
}

run().then(() => console.log(JSON.stringify(logs, undefined, 2)));

Did you find this article valuable?

Support MandrakeTech Blog by becoming a sponsor. Any amount is appreciated!