setTimeout не гарантирует, что метод обратного вызова будет вызван точно после заданной задержки. Это зависит от стека вызовов

Чтобы понять это ... давайте быстро посмотрим, как можно выполнить приведенный ниже код ...

console.log('line one started');
.
.
setTimeout(function(){
  console.log('may be after a sec');
},1000);
.
.
console.log('last line');
.
.
.
.
N-number of lines

Что произойдет, если мы запустим над кодом javascript…

самый первый будет создан Глобальный контекст выполнения (GEC), который будет помещен в стек вызовов.

Теперь код будет запускаться построчно

В консоли сначала мы можем видеть вывод первой строки и вывод последней строки, а позже мы можем увидеть печать консоли тайм-аута. Из-за цикла событий javascript.

Что такое eventLoop?

Выше фрагмента кода у нас есть основная функция, которая имеет 2 команды console.log, которые записывают «….» И «…» в консоль. Между ними зажат вызов setTimeout, который записывает «B» в консоль с временем ожидания 0 мс.

  1. Вызов основной функции сначала помещается в стек (как фрейм). Затем браузер помещает первый оператор в основной функции в стек, который называется console.log («первая строка запущена»). Этот оператор выполняется, и по завершении этот фрейм выскакивает. В консоли отображается алфавит «первая строка начата».
  2. Следующий оператор (setTimeout () с функцией обратного вызова () и временем ожидания 1000 мс) помещается в стек вызовов, и начинается выполнение. Функция setTimeout использует API браузера для задержки обратного вызова предоставленной функции. Затем кадр (с setTimeout) выскакивает после завершения передачи в браузер (для таймера).
  3. console.log («последняя строка») помещается в стек, пока в браузере запускается таймер для функции обратного вызова. В этом конкретном случае, поскольку предоставленная задержка составляла 0 мс, обратный вызов будет добавлен в очередь сообщений, как только браузер получит его (в идеале).

После выполнения последнего оператора в основной функции кадр main () выталкивается из стека вызовов, тем самым делая его пустым. . Чтобы браузер мог отправить любое сообщение из очереди в стек вызовов, стек вызовов сначала должен быть пустым. Вот почему, хотя задержка, указанная в setTimeout (), составляла 0 секунд, обратный вызов должен дождаться завершения выполнения всех кадров в стеке вызовов.

так вот почему setTimeout занимает больше заданного тайм-аута

Вот почему setTimeout занимает больше заданного таймаута

приведенный ниже пример кода занимает более 2 секунд.

function setTimeouTExmple(){
  console.log('A');
  setTimeout(
    function exec(){ console.log('B'); }
  , 2);
  runWhileLoopForNSeconds(3);
  console.log('C');
}
setTimeouTExmple();
function runWhileLoopFewSeconds(sec){
  let start = Date.now(), now = start;
  while (now - start < (sec*1000)) {
    now = Date.now();
  }
}

5.

Теперь обратный вызов помещается в стек вызовов и выполняется. На консоли отображается алфавит «может быть через 5 секунд». Весь этот процесс шагов представляет собой цикл событий javascript.

Это цикл событий javascript.