Ask
28

If await pauses the function anyway, how is it different from just calling things one after another?

I am struggling with what await actually buys me. Consider two versions of the same function: one calls three asynchronous operations with await on each line, the other is a hypothetical version where the same operations are synchronous and blocking.

In both cases the operations happen in order, each finishes before the next begins, and the function does not return until all three are done. From inside the function they look identical.

So what is the difference, and where does the benefit actually appear? I understand the syntax and not the point.

5 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @api_dilan · 21h ago

    There is a second, practical difference that shows up in your own code rather than in the runtime, and it is where most real performance wins come from.

    Because the operations are values rather than blocking statements, you can choose to not sequence them:

    // sequential — three round trips, one after another
    const a = await getA();
    const b = await getB();
    const c = await getC();
    
    // concurrent — three round trips at once, wait for all
    const [a, b, c] = await Promise.all([getA(), getB(), getC()]);
    

    If those three calls are independent, the second version finishes in the time of the slowest rather than the sum of all three. That option simply does not exist with blocking calls.

    The common mistake, once people learn await, is writing the first version everywhere out of habit. Whenever you see several awaits in a row, ask whether any of them actually depend on the ones above.

    22
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @js_runtime_jonas · 3h ago

    You are right that they look identical from inside the function, and that is precisely the design goal — the whole point of the syntax is that asynchronous code reads like sequential code.

    The difference is entirely outside the function.

    When your function hits await, it returns control to the runtime. The single thread is now free to do something else: handle an incoming request, respond to a click, run a timer callback, process another user's work. When the awaited operation completes, your function is resumed from where it stopped.

    A truly blocking call would hold the thread for the whole duration. Nothing else runs. On a server that means one slow database query stops every other request; in a browser it means the page freezes and does not even repaint.

    So await does block your function and does not block the thread. Those are two different things and the confusion between them is the entire question.

    30
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @architect_ayla · 2d ago

    The mental model that made this click for me: think of the thread as a single worker and each function as a task on a list.

    A blocking call is the worker standing at the printer waiting for it to finish. Nothing else on the list progresses.

    An await is the worker starting the printer, writing "come back to this when the printer beeps" on the task, putting it aside and picking up the next item. The task is paused; the worker never was.

    The reason this matters more in JavaScript than in some other environments is that there is only ever one worker. A language with a thread per request can afford blocking calls, because blocking one thread leaves the others running. With one thread, blocking is total — which is why the language went to the trouble of building syntax that makes non-blocking code look ordinary.

    27
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @maintainer_mika · 4h ago · 2 replies

    One thing worth knowing that trips people up later: await at the top of a function does not make the function synchronous for its caller.

    An async function returns a promise immediately, at the first await. The caller carries on unless it awaits too. So the sequencing you see inside the function only extends as far as the function, and forgetting to await further up is the single most common source of "why did this run out of order" bugs.

    14
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @js_runtime_jonas · 2d ago

      "It blocks your function, not the thread" is the sentence I needed six months ago. Everything else follows from it.

      9
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report