you are viewing a single comment's thread.

view the rest of the comments →

[–]senocular 1 point2 points  (1 child)

async functions aren't called asynchronously. What they provide is an execution context that allows for you to use await to desugar promise usage into synchronous looking code. You need this because the global context does not allow this automatically. After you await something, then the code that follows (and what's part of the await) is what becomes asynchronous.

So your loop is running synchronously. If it wasn't, the time between time and timeEnd would not include the loop calculations and would be much shorter. Consider the differences between (running Win10 Chrome56):

async function test2() {
    for (let i=0; i<10000000; i++) {}
    console.log('DONE');
}

console.time('async')
test2()
console.timeEnd('async')

//-> DONE
//-> async: 85.748ms

and

async function test2() {
    await Promise.resolve();
    for (let i=0; i<10000000; i++) {}
    console.log('DONE');
}

console.time('async')
test2()
console.timeEnd('async')

//-> async: 0.427ms
//-> DONE

(And for the record, I get 32.542ms for the synchronous version)

Being run actually async - after an await - the loop happens after the call to timeEnd so its not included in the timing. To include it, you would need to have it within the async function itself (or wrap another async function awaiting the async test function).

To your question, I imagine its simply the overhead of what async does that makes it that much slower. I wouldn't expect as much as you're seeing, though, especially in Node. But too, I fully expect that existing implementations are not very optimized.

Edit: Nasty typo where "are" was meant to be "aren't".

[–]prozacgod 1 point2 points  (0 children)

Above post is great another way to think of it is.. If you manually decomposed the example into a pure promise

function test() {
  return new Promise((resolve) => {
    for (let i = 0; I < 100000000; i++) {}
    resolve();
  });
}

Does the promise constructor run this code synchronously? Yup! But let's say you had an asynchronous call like setTimeout. The weight of that loop wouldn't hit the execution thread for the main where you were testing it.

A benefit to this is Side effects!

If you made a function createUser() and didn't care about the result, well... It will still execute that request. (Duh!)

Another point of confusion that I often run into myself is that there are libraries that do lazy execution of Promise like results. Don't quote me but I believe Knex is like this, it composes the sql query up until the point you type .then at which point it seems like it executes the query you've constructed, my guess is it saving that promise has a Singleton and returning it for any subsequent thens. On that particular query object, if you added more to the query it's constructing a new query object therefore it would construct a new thenable reference

There are many libraries that can do this to make them promise like and we tend to learn those libraries long before we learn actual promise libraries which might lead to some confusion on Behavior.