41

First, I have to mention that I already look through many questions in stackoverflow, but many doesn't answer my question. Not to mention many doesn't even have an answer.

How do I achieve the following, making sure functionB() executes after functionA() finishes?


Note: I do not want to convert my async functions to new Promise(resolve=>{...})
because I'll have to convert the someServiceThatMakesHTTPCall() as well, and any other async functions within the call stack, which is a big change.

  function functionThatCannotHaveAsyncKeyword() {
      functionA()
        .then(async function() {
            await functionB();
        })
        .then(function() {
            console.log('last');
        });
  }

  async function functionA() {
      console.log('first');
      await someServiceThatMakesHTTPCall();
  }

  async function functionB() {
      console.log('second');
      await someServiceThatMakesHTTPCall();
  }
5
  • 1
    NO, you haven't to convert your someServiceThatMakesHTTPCall, because there is no difference between async function and Promises Commented Feb 27, 2019 at 8:59
  • async () => true // returns Promise Commented Feb 27, 2019 at 9:01
  • 2
    I advise you to learn how promises work, because async/await is an extension of them (almost syntactical sugar!). I swear it's easier than you think :) Commented Feb 27, 2019 at 9:01
  • 1
    functionThatCannotHaveAsyncKeyword if that function is not meant to be awaited from something else, it can be async, because it will return a Promise<void> which will be ignored by the caller. Besides, return functionB() instead of the async-await is just enough for your case. Commented Feb 27, 2019 at 9:01
  • @CristianTraìna do you have a favorite tutorial for this? I should also post mine after I make some progress Commented Jul 21, 2022 at 18:05

4 Answers 4

55

Your approach using await in an async then callback will work, but it's unnecessarily complex if all you want to do is call the async function and have its result propagate through the chain. But if you are doing other things and want the syntax benefit of async functions, that's fine. I'll come back to that in a moment.

async functions returns promises, so you just return the result of calling your function:

function functionThatCannotHaveAsyncKeyword() {
    functionA()
        .then(function() {
            return functionB(someArgument);
        })
        .then(function() {
            console.log('last');
        }); // <=== Note: You need a `catch` here, or this function needs
            // to return the promise chain to its caller so its caller can
            // handle errors
}

If you want to pass functionA's resolution value into functionB, you can do it even more directly:

functionA()
    .then(functionB)
    // ...

When you return a promise from a then callback, the promise created by the call to then is resolved to the promise you return: it will wait for that other promise to settle, then settle the same way.

Example:

const wait = (duration, ...args) => new Promise(resolve => {
    setTimeout(resolve, duration, ...args);
});

async function functionA() {
    await wait(500);
    return 42;
}

async function functionB() {
    await wait(200);
    return "answer";
}

functionB()
.then(result => {
    console.log(result); // "answer"
    return functionA();
})
.then(result => {
    console.log(result); // 42
})
.catch(error => {
    // ...handle error...
});

Coming back to your approach using an async then callback: That works too, and makes sense when you're doing more stuff:

const wait = (duration, ...args) => new Promise(resolve => {
   setTimeout(resolve, duration, ...args);
});

async function functionA() {
    await wait(500);
    return 42;
}

async function functionB() {
    await wait(200);
    return "answer";
}

functionB()
.then(async (result) => {
    console.log(result); // "answer"
    const v = await functionA();
    if (v < 60) {
        console.log("Waiting 400ms...");
        await wait(400);
        console.log("Done waiting");
    }
    console.log(v);      // 42
})
.catch(error => {
    // ...handle error...
});

Sign up to request clarification or add additional context in comments.

20 Comments

Before this, I tried .then(async function() { return await functionB(); }) which doesnt work, i'll try your solution and see if it works and get back here
@ZhuHang - .then(async function() { return await functionB(); }) works just fine, you must have had some other problem in the code. But .then(function() { return functionB(); }) does the same thing more directly.
@t-j-crowder It seems so, I realised I have another problem that makes all my previous attempts seemed to be not working. Let me get back in a moment
@t-j-crowder To return promise chain back to its caller, i have to use new Promise => resolve/reject ?
@T.J.Crowder u know what? Sorry, it actually works. It's some other thing, again.
|
3

You can use promise inside the first method as

function functionThatCannotHaveAsyncKeyword() {
    return new Promise(async(resolve, reject)=> {
          await functionA();
          await functionB();
          console.log('last');
          resolve();    
      });
  }

  async function functionA() {
      console.log('first');
      await someServiceThatMakesHTTPCall();
  }

  async function functionB() {
      console.log('second');
      await someServiceThatMakesHTTPCall();
  }

2 Comments

i think u need to call resolve() after the console log right?
@RahulPatil Your solution is almost workable but seemed need to be updated in the way zhuhang.jasper told in his comment.
0

if someServiceThatMakesHTTPCall is async you can avoid all that by doing the following:

function functionThatCannotHaveAsyncKeyword() {
    functionA()
        .then(function() {
            return functionB()
        })
        .then(function() {
            console.log('last');
        });
  }

  function functionA() {
      console.log('first');
      return someServiceThatMakesHTTPCall();
  }

  function functionB() {
      console.log('second');
      return someServiceThatMakesHTTPCall();
  }

Comments

0

How do I achieve the following, making sure functionB() executes after functionA() finishes?

I think what you want is a third async function and then call that one. Like this:

function functionThatCannotHaveAsyncKeyword() {
    functionC()
    .then((resp) =>{
        // this code will execute after functioA and fucntionB finish. 
        // They will execute in that order thanks to functionC.
    });
}

async function functionC() {
    await functionA();
    await functionB();
}

async function functionA() {
    console.log('first');
    await someServiceThatMakesHTTPCall();
}

async function functionB() {
    console.log('second');
    await someServiceThatMakesHTTPCall();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.