Как setTimeout работает в Node.JS? - PullRequest
105 голосов
/ 01 мая 2011

Я полагаю, что, как только он будет выполнен, он окажется в очереди, но есть ли какая-то уверенность в том, что он будет вызван именно через X миллисекунд?Или другие тяжелые задачи в очереди задержат его?

Ответы [ 5 ]

158 голосов
/ 26 мая 2012

Семантика setTimeout примерно такая же, как в веб-браузере: аргумент времени ожидания равен минимуму мсек ожидания перед выполнением, не является гарантией.Кроме того, передача 0, не числа или отрицательного числа заставит его ждать минимальное количество мс.В Node это значение равно 1 мс, но в браузерах оно может достигать 50 мс.

Причина этого заключается в том, что JavaScript не имеет преимуществ перед JavaScript.Рассмотрим этот пример:

setTimeout(function () {
  console.log('boo')
}, 100)
var end = Date.now() + 5000
while (Date.now() < end) ;
console.log('imma let you finish but blocking the event loop is the best bug of all TIME')

Здесь используется следующий поток:

  1. запланировать тайм-аут на 100 мс.
  2. busywait на 5000 мс.
  3. returnк циклу событий.проверьте наличие таймеров, ожидающих выполнения, и выполните.

Если бы это было не так, то один бит JavaScript мог «прервать» другой.Мы должны были бы настроить мьютексы и семафоры и тому подобное, чтобы исключить возможность слишком сложного рассуждения подобного кода:

var a = 100;
setTimeout(function () {
  a = 0;
}, 0);
var b = a; // 100 or 0?

Однопоточность выполнения JavaScript в Node значительно упрощает работу счем большинство других стилей параллелизма.Конечно, компромисс заключается в том, что часть программы с плохим поведением может блокировать все это с помощью бесконечного цикла.

Является ли это лучшим демоном для битвы, чем сложностью вытеснения?Это зависит.

40 голосов
/ 01 мая 2011

Идея неблокирования заключается в том, что итерации цикла выполняются быстро. Таким образом, для итерации для каждого тика должно потребоваться достаточно короткое время, чтобы setTimeout был точным с разумной точностью (отключено, возможно, <100 мс или около того). </p>

Теоретически ты прав. Если я напишу приложение и заблокирую галочку, setTimeouts будет отложено. Итак, чтобы ответить на ваш вопрос, кто может обеспечить выполнение setTimeouts вовремя? Вы, написав неблокирующий код, можете контролировать степень точности практически до любой разумной степени точности.

Пока javascript является «однопоточным» с точки зрения выполнения кода (исключая веб-работников и тому подобное), это всегда будет происходить. Однопоточная природа в большинстве случаев является огромным упрощением, но для успеха требуется неблокирующая идиома.

Попробуйте этот код либо в своем браузере, либо в узле, и вы увидите, что нет гарантии точности, напротив, setTimeout будет очень поздно:

var start = Date.now();

// expecting something close to 500
setTimeout(function(){ console.log(Date.now() - start); }, 500);

// fiddle with the number of iterations depending on how quick your machine is
for(var i=0; i<5000000; ++i){}

Если интерпретатор не оптимизирует цикл (чего не происходит в chrome), вы получите что-то тысячами. Снимите петлю, и вы увидите, что это 500 на носу ...

8 голосов
/ 01 мая 2011

Единственный способ обеспечить выполнение кода - поместить логику setTimeout в другой процесс.

Используйте дочерний модуль процесса для запуска новой программы node.js, которая выполняет вашу логику и передает данные этому процессу через некоторый поток (возможно, tcp).

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

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

Как правило, для масштабирования кода важно использовать дочерние процессы и запускать приложения с несколькими узлами в качестве отдельных процессов вместе с балансировщиком нагрузки или общим хранилищем данных (например, redis).

6 голосов
/ 06 февраля 2017

setTimeout(callback,t) используется для запуска обратного вызова по крайней мере через t миллисекунду .Фактическая задержка зависит от многих внешних факторов, таких как детализация таймера ОС и загрузка системы.

Таким образом, существует вероятность того, что она будет вызываться немного позже установленного времени, но никогда не будет вызываться раньше.

Таймер не может занимать более 24,8 дней.

6 голосов
/ 12 января 2017

setTimeout является разновидностью Thread , она содержит операцию в течение заданного времени и выполняется.

setTimeout(function,time_in_mills);

здесь первый аргумент должен быть функциейtype, Например, если вы хотите напечатать свое имя через 3 секунды, ваш код должен быть примерно таким, как показано ниже.

setTimeout(function(){console.log('your name')},3000);

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

setTimeout(function(){yourOtherMethod(parameter);},3000);

счастливое кодирование nodejs:)

...