Home > database >  How to run code asynchronously from within an async function?
How to run code asynchronously from within an async function?

Time:11-16

If you call an async function from non-async code, anything after the await runs asynchronously with respect to the caller:

async function asyncInner() {
  console.log('before asyncInner');
  await Promise.resolve()
  console.log('after asyncInner');
}

console.log('start');
asyncInner()
console.log('end');
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

In other words, this prints:

start
before asyncInner
end
after asyncInner

But if you call this async function from within another async function:

async function asyncInner() {
  console.log('before asyncInner');
  await Promise.resolve()
  console.log('after asyncInner');
}

async function asyncOuter() {
  console.log('before asyncOuter');
  await asyncInner();
  console.log('after asyncOuter');
}

console.log('start');
asyncOuter()
console.log('end');
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

you get:

start
before asyncOuter
before asyncInner
end
after asyncInner
after asyncOuter

In other words, the inner method completes synchronously with respect to the outer method. Why is this and how could it be written so that asyncOuter completed before the asyncInner?

(I know I could use a setTimeout for this, but I'd prefer to avoid using callbacks, because one of the nice things about async is avoiding callback hell.)

CodePudding user response:

In other words, the inner method completes synchronously with respect to the outer method. Why is this and how could it be written so that asyncOuter completed before the asyncInner?

It's not actually synchronous, but you're right that it will wait for the inner function to finish before continuing the outer function. The reason it will wait is because you told it to wait with the await keyword. If you don't want it to wait, simply leave that out.

async function asyncInner() {
  console.log('before asyncInner');
  await Promise.resolve()
  console.log('after asyncInner');
}

async function asyncOuter() {
  console.log('before asyncOuter');
  asyncInner(); // <--------- removed the await
  console.log('after asyncOuter');
}

console.log('start');
asyncOuter()
console.log('end');
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

@Keith: I see that I was confusing "synchronous" with "waited".

Even then it's kind of vague. await in Javascript is really some fancy syntax sugar for promise.then(result => {}) So nothing really waits, it's just callback hell is converted into something that looks synchronous, and as such much easier to reason with.

It might make more sense if we remove await, and do it the old fashioned way of using the thenable.

So below I have converted your example to run without await, and as you can see it gives the same result, but this time we are using callback's. So if you understand callback's, it then makes more sense why you get the result you do.

function asyncInner() {
  console.log('before asyncInner');
  return Promise.resolve().then(r => 
    console.log('after asyncInner'));
}

function asyncOuter() {
  console.log('before asyncOuter');
  return asyncInner().then(() => 
    console.log('after asyncOuter'));
}

console.log('start');
asyncOuter()
console.log('end');
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related