Why does this line of code with 'await' trigger microtask queue processing?

前端 未结 1 1320
情深已故
情深已故 2021-02-01 09:42

The following quotes are my primary references for understanding microtask queue processing:

Microtasks (which promises use) are processed when the JS sta

相关标签:
1条回答
  • 2021-02-01 10:09

    "Microtasks (which promises use) are processed when the JS stack empties." -Jake Archibald (doesn't make sense to me)

    The "call stack" is the list of things that are currently executing:

    function foo() {
      debugger;
      console.log('foo');
    }
    
    function bar() {
      foo();
      debugger;
    }
    
    bar();
    

    When we hit the first debugger statement, the script is still executing, as is bar, as is foo. Since there's a parent-child relationship, the stack is script > bar > foo. When we hit the second debugger statement, foo has finished executing, so it's no longer on the stack. The stack is script > bar.

    The microtask queue is processed until it's empty, when the stack becomes empty.

    "One go-around of the event loop will have exactly one task being processed from the macrotask queue (this queue is simply called the task queue in the WHATWG specification). After this macrotask has finished, all available microtasks will be processed, namely within the same go-around cycle." - stackoverflow

    Edit: I kept reading "macrotask" above as "microtask". There isn't really such a thing as a macrotask queue in the browser, it's just a task queue.

    Although it's true that there's a microtask processing point after processing a task, it's only really there to handle specifications that queue tasks to queue microtasks, without calling into JS first. Most of the time, the microtask queue is emptied when the JS stack empties.

    From stepping through this snippet w/ debugger, the execution stack does not appear empty when these .then( callback ) microtasks are processed/executed.

    The stack will never be empty while callbacks are being executed, since the callback itself will be on the stack. However, if this is the only thing on the stack, you can assume the stack was empty before this callback was called.

    Chrome's devtools tries to be helping in maintaining an "async" stack, but this isn't the real stack. The real stack is everything before the first "async" line.

    Are regular functions like f2() considered a task

    Being a task or a microtask isn't a property of a function. The same function can be called within a task, a microtask, and other parts of the event loop such as rendering. Eg:

    function foo() {}
    
    // Here, I'll call foo() as part of the current task:
    foo();
    
    // Here, I'll let the browser call foo() in a future task:
    setTimeout(foo);
    
    // Here, I'll let the browser call foo() in a microtask:
    Promise.resolve().then(foo);
    
    // Here, I'll let the browser call foo() as part of the render steps:
    requestAnimationFrame(foo);
    

    In your example, f2 is not called within a microtask. It's kinda like this:

    function three() {}
    function two() {}
    
    async function one() {
      await two();
      three();
    }
    
    one();
    

    Here, one() is called within the task that executed the script. one() calls two() synchronously, so it runs as part of the same task. We then await the result of calling two(). Because we await, the rest of the function runs in a microtask. three() is called, so it runs in the same microtask.

    0 讨论(0)
提交回复
热议问题