«Микрозадачи (которые обещают использовать) обрабатываются, когда стек JS очищается».Джейк Арчибальд (для меня это не имеет смысла)
"Стек вызовов" - это список вещей, которые выполняются в данный момент:
function foo() {
debugger;
console.log('foo');
}
function bar() {
foo();
debugger;
}
bar();
Когда мы нажимаем первыйоператор отладчика, сценарий все еще выполняется, как bar
, как foo
.Поскольку существуют отношения родитель-потомок, стек равен script > bar > foo
.Когда мы нажимаем на второй оператор отладчика, foo
завершил выполнение, поэтому он больше не находится в стеке.Стек составляет script > bar
.
Очередь микротрассы обрабатывается до тех пор, пока она не станет пустой, когда стек станет пустым.
"Один цикл обработки событий будет иметь ровно одинЗадача, обрабатываемая из очереди макросов (эта очередь называется просто очередью заданий в спецификации WHATWG). После того, как эта макросзадача будет завершена, будут обработаны все доступные микрозадачи, а именно в рамках одного цикла обращения. "- stackoverflow
Edit : я продолжал читать "macrotask" выше как "microtask".На самом деле в браузере нет такой очереди как макрозадача, это просто очередь задач.
Несмотря на то, что после обработки задачи есть точка обработки микрозадачи, она действительно существует только для обработки спецификаций, которыеставить задачи в очередь для выполнения микрозадач без предварительного вызова JS.Большую часть времени очередь микрозадач освобождается, когда стек JS очищается.
При переходе через этот фрагмент с отладчиком стек выполнения не отображается пустым, когда эти .then (обратный вызов) микрозадачиобработано / выполнено.
Стек никогда не будет пустым во время выполнения обратных вызовов, поскольку сам обратный вызов будет находиться в стеке.Однако, если это единственное в стеке, вы можете предположить, что стек был пуст до того, как был вызван этот обратный вызов.
devtools в Chrome пытается помочь в поддержании "асинхронного" стека, но это не такреальный стек.Реальный стек - это все, что находится до первой строки «async».
Являются ли обычные функции, такие как f2 (), задачей
Быть задачей или микрозадачей не значитсвойство функции.Эта же функция может быть вызвана внутри задачи, микрозадачи и других частей цикла событий, таких как рендеринг.Например:
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);
В вашем примере f2
- это , а не , вызываемый в микрозадаче.Это примерно так:
function three() {}
function two() {}
async function one() {
await two();
three();
}
one();
Здесь one()
вызывается внутри задачи, которая выполнила сценарий.one()
вызывает two()
синхронно, поэтому он выполняется как часть той же задачи.Затем мы await
результат вызова two()
.Поскольку мы await
, остальная часть функции выполняется в микрозадаче.three()
называется, поэтому он выполняется в одной и той же микрозадаче.