Search code examples
javascriptpromisees6-promise

How to use async alternative for Promise.resolve().then()?


Run the snippets and look at their durations you'll see that first snippet executes log('Synchronous 2') before billion loops done. It spent 0ms, but 2nd snippet using async keyword blocks log('Synchronous 2')until the loop is finished.

const tick = Date.now();
const log = (v) => console.log(`${v} \n Elapsed: ${Date.now() - tick}ms`);

const notBlocked = () => {
    return Promise.resolve().then(() =>  {
        let i = 0;
        while(i < 1000000000) { i++; } //runs asynchronically
        return '🐷 billion loops done';
    })
}

log('🥪 Synchronous 1');
notBlocked().then(log);
log('🥪 Synchronous 2');

The log('Synchronous 2') is blocked

const tick = Date.now();
const log = (v) => console.log(`${v} \n Elapsed: ${Date.now() - tick}ms`);

const notBlocked = async() => {
    let i = 0;
    while(i < 100000000) { i++; } //runs synchronically and blocks main thread
    return '🐷 billion loops done';
}

log('🥪 Synchronous 1');
notBlocked().then(log);
log('🥪 Synchronous 2');


Solution

  • Async functions run synchronously until they hit an await, so if your goal is to use an async function to delay some code as a microtask, you'll need to stick an await in there, even if it's awaiting something useless.

    const tick = Date.now();
    const log = (v) => console.log(`${v} \n Elapsed: ${Date.now() - tick}ms`);
    
    const notBlocked = async () => {
      await undefined; // yield until the microtasks run
      let i = 0;
      while(i < 1000000000) { i++; }
      return '🐷 billion loops done';
    }
    
    log('🥪 Synchronous 1');
    notBlocked().then(log);
    log('🥪 Synchronous 2');