0

I recently read a book about async and await patterns, there's chapter about deferred await or early init. The book says:

This allows a structure that starts async processing early but only stops for it when the result is needed.

const wait = (ms) => new Promise(res => setTimeout(res, ms));

const fn = async () => {
  console.log("starting");
  await wait(100); // I suppose await should pause the execution
  console.log("end");
}

(async () => {
  const fnPromise = fn();
  console.log("after"); // However after is printed brfore end
  await fnPromise;
})();

And if I change the code a bit

(async () => {
  await fn(); // looks like the inner await only takes effect when I await an async function
  console.log("after"); // after is printed after end
})();

I mean what's the difference between await an async function and directly calling it. Is there any best pratice about when to await or when not to await an async function. Does await truly block the execution, especially combined with timers. Thanks to @asynts's snippet, I'll post it here

let samples = 100 * 1000 * 1000;
let chunk = 100000;

async function run() {
    let sum = 0.0;
    for(let i=0; i<samples; i++) {
        sum += Math.random();

        if (i % chunk === 0) {
            console.log("finished chunk")
            // wait for the next tick
            await new Promise(res => setTimeout(res, 0));
            // If await truly blocks the execution, rest of the code are all waiting? 
            // If await doesn't block the execution, what's the point to await here
        }
    }

    let mean = sum / samples;
    console.log("finished computation", mean);
}

setTimeout(run, 0);
crazyones110
  • 296
  • 3
  • 18
  • As far as I can understand, `await` an async function can cause **inner** `await` block the execution, but does tht mean we need to `await` all the async functions all the way up? – crazyones110 Sep 26 '21 at 14:55
  • I suggest you, to use a debugger, In order to see the control flow of an async function... – Nur Sep 26 '21 at 15:00
  • 1
    The key here is that `await` only suspends execution of the containing function, not the code that comes after it. At the point you hit an await`, that function is suspended and it ***immediately*** returns a promise and the code after the function call receives that returned promise and execution continues. It's up to the calling code to do something useful with that returned promise. – jfriend00 Sep 26 '21 at 15:22
  • @jfriend00 So if you want to make sure the code after outer `await` to be suspended, use an outer `await`. Or if you want to let code flow, do not use outer `await` (which means ignore the promise the async function returns, though the containing function will still be suspended due to inner `await`) – crazyones110 Sep 27 '21 at 03:47
  • Code is going to flow at some level. Otherwise, you're deadlocked and NO events can happen, not even the ones that will finish the asynchronous operations. You can use an `await` at the outer level if that's the desire of the caller (the caller wants to wait for completion). Otherwise, I don't really understand what you're trying to accomplish. You structure the code according to your programming objective - their is no generic structure that works for all cases. And, you always should be handling rejected promises at some level with `.catch()` or ` try/catch` around an `await`. – jfriend00 Sep 27 '21 at 04:13

1 Answers1

0

What's the difference between await an async function and directly calling it.

Well, you already observed the difference clearly in your first two snippets.

Is there any best practice about when to await or when not to await an async function?

Yes: always do it immediately. Do not let promises sit around un-awaited (like your fnPromise variable).

Not doing so is not necessarily wrong, but it increases the likelihood of mistakes:

Bergi
  • 630,263
  • 148
  • 957
  • 1,375