skip to Main Content

I have the following code:

async function get_exam_score() {
    const exam_score = Math.random() * 10;
    if (exam_score < 5) {
        throw("You failed");
    }
}

const promise = get_exam_score();
console.log("TRY:", promise);

and if I run that above code, console.log() shows that the async function promise has already been settled with either a fulfilled or rejected state. Code & execution

How is that possible? Should not the promise still be in a pending state since its microtask with the result should not be able to execute until the callstack is empty?

I would like to know in-depth how is JavaScript managing the callstack, microtask queue, event loop and anything relevant to this topic. So that it leads to the promise being in a settled state by the time console.log() is executed.

Interestingly enough, if I change the function get_exam_score to explicitly return a Promise. Then, I do get that the promise is indeed in a pending state. Code & execution result

async function get_exam_score() {
    return new Promise((resolve, reject) => {
        const exam_score = Math.random() * 10;
        if (exam_score < 5) {
            reject("You failed");
        }
        resolve("You passed");
    });
}

const promise = get_exam_score();
console.log("TRY:", promise);

Why are these 2 code samples generating different outputs?


EDIT: Removed try / catch block as it was misleading. Additionally, added a code example which actually returns a promise with a pending status.

2

Answers


  1. Should not the promise still be in a pending state since its microtask with the result should not be able to execute until the callstack is empty?

    That promise is never in a pending state. It is settled from the start. But JS code can only know about that state by registering a then callback (its first or second argument) — or issuing an await. The microtask that is queued to get that callback executed is only informing about the promise’s state and value. That happens asynchronously, even though the promise’s state can be set synchronously. The agent (browser) knows about the promise’s state without attaching a then callback, which is why the console can show the promise’s state synchronously, but with JS code it is not possible to inspect a promise’s state synchronously.

    If I change the function get_exam_score to explicitly return a Promise. Then, I do get that the promise is indeed in a pending state.

    When you return a promise in an async function, there are two promises involved: the promise in the return statement (let’s call it A), and the promise returned by the async function (let’s call it B). Those are distinct promises. Promise B is "locked-in" to promise A. Implicitly this is done "behind the scenes" by executing a then method call on promise A and have a callback resolve promise B in the same way as promise A.

    As this then-callback executes asynchronously, we can conclude that an async function that executes a return statement with a promise as operand always returns a pending promise — no matter what the initial state is of the promise that is given to the return statement.

    Login or Signup to reply.
  2. An async function executes synchronously until it either throws outside a catch statement, returns a value, or executes an await statement.

    • if it executes an await operator it returns a pending promise which will be rejected later if the await operator or function code following it throws without being caught, or which will be fulfilled with the function’s ultimate return value if neither the await operator nor any code following it throws an uncaught error.

    • If the async function call throws an uncaught error before await is encountered, the function synchronously returns a rejected promise with the error as its rejection reason.

    • If the async function returns synchonously with error (and no await operator was encountered), it returns a fulfilled promise with the return value as promise data.

    There are no other cases to consider.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search