«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > SetTimeout — это не то же самое, что вы думаете

SetTimeout — это не то же самое, что вы думаете

Опубликовано 19 августа 2024 г.
Просматривать:153

Когда разработчики впервые сталкиваются с setTimeout в JavaScript, он часто кажется простым инструментом для задержки выполнения функции. Однако понимание того, как setTimeout взаимодействует со средой выполнения JavaScript и циклом событий, может выявить неожиданное поведение, особенно в определенных условиях. И дело не только в setTimeout; аналогичные сложности возникают и с setInterval и другими асинхронными функциями.

Цикл событий: краткий обзор
JavaScript является однопоточным, то есть одновременно может выполняться только один фрагмент кода. Несмотря на это, цикл событий позволяет JavaScript выполнять неблокирующие операции. Это достигается за счет переноса таких задач, как таймеры, сетевые запросы или операции ввода-вывода, на браузер или API Node.js. После завершения этих задач их функции обратного вызова повторно ставятся в очередь для выполнения в цикле событий.

SetTimeout is Not the Same as You Think

Как работает setTimeout
Когда вы вызываете setTimeout, вы просите движок JavaScript выполнить функцию через указанный период. Это делается путем добавления функции обратного вызова в очередь цикла событий. Однако указанная задержка — это минимальное время, которое механизм должен ждать перед добавлением обратного вызова в очередь, а не гарантированное время выполнения. Вот как это работает подробно:

  1. Первоначальный вызов: когда setTimeout вызывается с функцией обратного вызова и задержкой, движок JavaScript регистрирует это в среде веб-API, предоставляемой браузером или Node.js.

  2. Таймер: веб-API запускает таймер с указанной задержкой. В течение этого периода основной стек вызовов продолжает выполнять любой синхронный код, следующий за вызовом setTimeout.

  3. Очередь обратного вызова: по истечении времени таймера веб-API не выполняет обратный вызов немедленно. Вместо этого он перемещает функцию обратного вызова в очередь событий.

  4. Цикл событий: в игру вступает цикл событий, который постоянно отслеживает стек вызовов и очередь событий. Если стек вызовов пуст, то есть в данный момент нет выполняемых задач, цикл обработки событий берет первую функцию из очереди событий и помещает ее в стек вызовов для выполнения.

  5. Выполнение: функция обратного вызова окончательно выполняется, когда она достигает вершины стека вызовов.

Важно отметить, что если стек вызовов занят другими задачами по истечении времени таймера, могут возникнуть дополнительные задержки перед выполнением функции обратного вызова. Это связано с тем, что цикл обработки событий должен дождаться очистки стека вызовов, прежде чем он сможет обработать функцию обратного вызова из очереди событий.

SetTimeout is Not the Same as You Think


Проблема блокировки
Распространенное недоразумение заключается в том, что setTimeout всегда будет выполнять обратный вызов после точной указанной задержки. Если цикл событий заблокирован синхронным кодом, например, бесконечным циклом или длительным вычислением, обратный вызов не будет выполнен до тех пор, пока цикл событий не освободится.

Рассмотрим следующий сценарий:

console.log('Program started at: '   new Date().toLocaleTimeString());

const programStartTime = Date.now();

function blockExecutionForThirtySeconds() {
  while (true) {
    const currentTime = Date.now();
    if (currentTime - programStartTime > 30000) {
      console.log('Blocking execution completed after 30 seconds...');
      return true;
    }
  }
}

console.log('Setting setTimeout for 1 second.');
setTimeout(() => {
  console.log('setTimeout executed after 30 seconds instead of 1 second: '   new Date().toLocaleTimeString());
}, 1000);

blockExecutionForThirtySeconds();

В этом примере функция blockExecutionForThirtySeconds блокирует цикл событий с помощью бесконечного цикла, который выполняется в течение 30 секунд. Несмотря на то, что setTimeout настроен на выполнение через 1 секунду, он запустится только после завершения блокаExecutionForThirtySeconds, то есть через 30 секунд.

SetTimeout is Not the Same as You Think

Последствия из реальной жизни
Понимание этого поведения имеет решающее значение для разработчиков, особенно при написании кода, включающего таймауты, интервалы или асинхронную обработку. Непонимание того, как работает setTimeout, может привести к проблемам с производительностью и ошибкам, которые трудно отследить. Если фрагмент кода выполняет тяжелые вычисления или длительные задачи и блокирует цикл событий, все обратные вызовы setTimeout, разрешения обещаний и другие асинхронные операции будут отложены до тех пор, пока цикл событий не освободится.

Заключение
setTimeout — мощный инструмент в JavaScript для задержки выполнения кода, но важно понимать его нюансы. Указанная задержка — это минимальное время ожидания, прежде чем функцию можно будет поставить в очередь для выполнения. Фактическое время выполнения зависит от состояния цикла событий. Освоение асинхронных операций и управления циклами событий является ключом к написанию эффективных и быстро реагирующих приложений JavaScript.

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/mrrishimeena/settimeout-is-not-the-same-as-you-think-44ep?1. Если есть какие-либо нарушения, свяжитесь с [email protected], чтобы удалить это
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3