skip to Main Content

I have two async functions in a module. Currently they are both just meant to wait, since the actual logic isn’t implemented yet.

Async module

export async function foo() {
  return new Promise(resolve => {
    setTimeout(() => {
       console.log('foo');
    }, 500);
  });
}

export async function bar() {
  return new Promise(resolve => {
    setTimeout(() => {
       console.log('bar');
    }, 500);
  });
}

In the main code, I am calling these two functions sequentially in another function. I want foo to finishe before bar starts, so I’m using await.

Main code

import { foo, bar } from './myModule'

async function submit() {
  await foo();
  await bar();

  // do other stuff
  otherStuff();
}

submit();

This code logs ‘foo’ but then stops working. It doesn’t call bar nor otherStuff. What am I doing wrong?

Additionally, according to this answer, async functions always return a Promise. I tried removing the Promise from foo and bar, since both are declared as async, but then all functions are called without waiting for the previous one to finish, i.e. await doesn’t have any effect at all.

2

Answers


  1. When there are callbacks in your code – because of a library or the user of setTimeout() for example – you may be forced to create promises by hand.

    In this case, what you did is correct, but you forgot to resolve those promises! Said differently: you promised something, but you didn’t keep your word.

    Here is the working code:

    export async function foo() {
      return new Promise(resolve => {
        setTimeout(() => {
           console.log('foo');
           resolve();
        }, 500);
      });
    }
    
    export async function bar() {
      return new Promise(resolve => {
        setTimeout(() => {
           console.log('bar');
           resolve();
        }, 500);
      });
    }
    

    Additionally, according to this answer, async functions always return a Promise. I tried removing the Promise from foo and bar, since both are declared as async, but then all functions are called without waiting for the previous one to finish, i.e. await doesn’t have any effect at all.

    When the answer says "async functions always return a Promise", it’s because declaring a function as async will create a wrapper for you:

    async function foo() {
      return 1;
    }
    

    is a sugar syntax for:

    function foo(): Promise<number> {
      return Promise.resolve(1)
    }
    

    which works the same as:

    function foo(): Promise<number> {
      return new Promise(resolve => {
        resolve(1)
      })
    }
    

    But since you are currently using setTimeout(), which uses a callback, this is not a promise. Something needs to be called back. So simply adding the sugar syntax async will not do what you intend.

    For example, imagine you attempt to do this:

    async function foo() {
      setTimeout(() => {
         console.log('foo');
      }, 500);
    }
    

    This will be equivalent to:

    function foo(): Promise<ReturnType<typeof setTimeout>> {
      return Promise.resolve(
        setTimeout(() => {
           console.log('foo');
        }, 500);
      )
    }
    

    Which is not what you want.

    Login or Signup to reply.
  2. In JS, when you create a new Promise using the Promise constructor, you need to call the resolve function because it’s an integral part of how promises work. The resolve function is used to fulfill a promise, indicating that a certain asynchronous operation has completed successfully, and the promise should transition from a pending state to a fulfilled state. This is essential for handling asynchronous operations.

    So in this case, this code works:

    async function foo() {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log('foo')
                resolve('foo')
            }, 200);
        });
    }
    
    async function bar() {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log('bar')
                resolve('bar')
            }, 200);
        });
    }
    
    async function submit() {
        await foo()
        await bar()
    }
    
    submit()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search