Если вы знакомы с программированием JavaScript на стороне клиента, вы, возможно, использовали функции SetTimeout и SetInterval, которые позволяют задержки в течение определенного периода времени перед запуском функции. Например, следующий код, загруженный на веб -страницу, через 1 секунду «Привет» будет добавлен после документа страницы:
Кода -копия выглядит следующим образом:
var OneSecond = 1000 * 1; // одна секунда = 1000 x 1 мс
settimeout (function () {
document.write ('<p> Привет. </p>');
}, один из второго);
и SetInterval позволяет повторять выполнение функций через указанные временные интервалы. Если следующий код введен в веб -страницу, это приведет к тому, что следующее предложение «Привет» будет добавлено в документ страницы каждую секунду:
Кода -копия выглядит следующим образом:
var OneSecond = 1000 * 1; // одна секунда = 1000 x 1 мс
setInterval (function () {
document.write ('<p> Привет. </p>');
}, один из второго);
Поскольку сеть уже давно становится платформой для создания приложений, а не простой статической страницей, этот вид аналогичного спроса становится все чаще. Эти функции планирования задач помогают разработчикам реализовать периодическую проверку форм, задержать удаленную синхронизацию данных или взаимодействия пользовательского интерфейса, которые требуют отсроченных ответов. Узел также реализует эти методы полностью. На стороне сервера вы можете использовать их для повторения или задержки выполнения многих задач, таких как срок годности кэша, очистка пула соединений, истечение сессии, опрос и многое другое.
Выполнить с помощью функции задержки SetTimeout
SetTimeout может создать план выполнения, который запускает указанную функцию один раз в определенное время в будущем, например:
Кода -копия выглядит следующим образом:
var timeout_ms = 2000; // 2 секунды
var timeout = setTimeout (function () {
console.log («Втирание!»);
}, timeout_ms);
Как и клиент Javascript, SetTimeout принимает два параметра. Первый параметр - это функция, которую необходимо отложить, а второй параметр - время задержки (в миллисекундах).
SetTimeout возвращает рукоятку тайм -аута, которая является внутренним объектом. Вы можете использовать его в качестве параметра для вызова cleartimeout, чтобы отменить таймер. За исключением этого, эта ручка не имеет никакого эффекта.
Используйте ClearTimeOut, чтобы отменить план выполнения
После получения направления тайм -аута вы можете использовать ClearTimeout для отмены плана выполнения функции, например:
Кода -копия выглядит следующим образом:
var timeouttime = 1000; // одна секунда
var timeout = setTimeout (function () {
console.log («Втирание!»);
}, тайм -время);
ClearTimeout (тайм -аут);
В этом примере таймер никогда не будет инициирован и не выведет слова «время!». Вы также можете отменить план выполнения в любое время в будущем, например, следующий пример:
Кода -копия выглядит следующим образом:
var timeout = setTimeout (function a () {
console.log («Втирание!»);
}, 2000);
settimeout (function b () {
ClearTimeout (тайм -аут);
}, 1000);
Код определяет две функции A и B, которые выполняются задержаны. Функция A планируется выполнять через 2 секунды, и B планируется выполнять через 1 секунду, потому что функция B выполняется в первую очередь, и она отменяет план выполнения A, поэтому A никогда не будет работать.
Разработать и отменить повторяющийся план выполнения функции
SetInterval похож на SetTimeout, но он будет многократно выполнять функцию в указанный интервал времени. Вы можете использовать его для периодического запуска программы для выполнения некоторых других задач, которые необходимо повторить, такие как очистка, сбор, ведение журнала, получение данных, опросы и т. Д.
Следующий код будет выводить «тик» на консоли каждую секунду:
Кода -копия выглядит следующим образом:
var period = 1000; // 1 секунда
setInterval (function () {
console.log ("tick");
}, период);
Если вы не хотите, чтобы он работал навсегда, вы можете использовать ClearInterval (), чтобы отменить таймер.
SetInterval возвращает ручку плана выполнения, которая может использоваться в качестве параметра для очистки для отмены плана выполнения:
Кода -копия выглядит следующим образом:
var интервал = setInterval (function () {
console.log ("tick");
}, 1000);
//…
ClearInterval (интервал);
Используйте процесс.
Иногда клиент -программист JavaScript использует SetTimeout (обратный вызов, 0), чтобы отложить задачу на короткий период времени. Второй параметр - 0 миллисекунд. Это говорит JavaScript выполнить эту функцию обратного вызова сразу после обработки всех ожидающих событий. Иногда этот метод используется для задержки выполнения операций, которые не нужно выполнять немедленно. Например, иногда вам нужно начать играть в анимации или делать некоторые другие вычисления после обработки пользовательского события.
В узле, как и буквальное значение «петля событий», цикл событий работает в цикле, который обрабатывает очереди событий, и каждый раунд в цикле событий называется тиком.
Вы можете позвонить в функцию обратного вызова один раз каждый раз, когда цикл событий запускает выполнение следующего раунда (следующее тик), которое является именно принципом процесса.
Используя process.nexttick (обратный вызов) вместо SetTimeout (обратный вызов, 0), ваша функция обратного вызова будет выполнена сразу после обработки события в очереди. Это намного быстрее, чем очередь тайм -аута JavaScript (измеряется временем процессора).
Вы можете отложить функцию до следующего цикла событий и запустить ее так:
Кода -копия выглядит следующим образом:
process.nexttick (function () {
my_exply_computation_function ();
});
Примечание. Объект процесса является одним из немногих глобальных объектов в узле.
Блокировка петли событий
Время выполнения узла и JavaScript использует однопоточный цикл событий. Каждый цикл, во время выполнения использует функцию обратного вызова для обработки следующего события в очереди. Когда событие выполнено, цикл событий получает результат выполнения и обрабатывает следующее событие, повторяя это до тех пор, пока очередь события не станет пустой. Если один из обратных вызовов занимает много времени, чтобы запустить, цикл событий не может справиться с другими ожидающими событиями в течение этого времени, что может сделать приложение или обслуживание очень медленным.
При обработке событий, если используются чувствительные к памяти функции или чувствительные к процессору функции, цикл событий станет медленным, и будет накапливаться большое количество событий, которые не могут быть обработаны во времени или даже блокировать очередь.
См. Следующий пример блокировки цикла событий:
Кода -копия выглядит следующим образом:
process.nexttick (function nexttick1 () {
var a = 0;
while (true) {
a ++;
}
});
process.nexttick (function nexttick2 () {
console.log ("Next Tick");
});
setTimeout (функция timeout () {
console.log («Тайм -аут»);
}, 1000);
В этом примере функции NextTick2 и Timeout не имеют шансов запустить, независимо от того, как долго они ждут, потому что цикл событий блокируется бесконечным циклом в следующей функции, и он не будет работать, даже если функция тайм -аута будет выполнена через 1 секунду.
Когда используется SetTimeout, функции обратного вызова добавляются в очередь плана выполнения, и в этом случае они даже не добавляются в очередь. Хотя это является экстремальным примером, вы можете увидеть, что выполнение чувствительной к процессору задачи может блокировать или замедлить петлю события.
Выйти из петли событий
Используя Process.nexttick, некритическая задача может быть отложена на следующий раунд цикла событий (Tick) до выполнения, который может освободить цикл события, чтобы он мог продолжать выполнять другие ожидающие события.
Смотрите следующий пример. Если вы планируете удалить временный файл, но не хотите, чтобы функция обратного вызова события Data ждала этой операции ввода -вывода, вы можете задержать его так:
Кода -копия выглядит следующим образом:
stream.on ("data", function (data) {
Stream.end («Мой ответ»);
process.nexttick (function () {
fs.unlink ("/path/to/file");
});
});
Используйте SetTimeout вместо SetInterval, чтобы обеспечить последовательность выполнения функций
Предположим, вы планируете разработать функцию, называемую MY_ASYNC_FUNCTION, которая может выполнять некоторые операции ввода -вывода (например, файлы журнала анализа) и намеревается выполнять периодически. Вы можете реализовать его с SetInterval, как это:
Кода -копия выглядит следующим образом:
var -интервал = 1000;
setInterval (function () {
my_async_function (function () {
console.log ('my_async_function закончил!');
});
}, интервал); // Примечание переводчика: я добавил предыдущий ", интервал", и автор должен был пропустить его из -за опечатки
Вы должны быть в состоянии убедиться, что эти функции не выполняются одновременно, но если вы используете SetInterval, вы не можете это гарантировать. Если функция my_async_function работает на один миллисекунд длиннее интервальных переменных, они будут выполняться одновременно, а не последовательно в последовательности.
Примечание переводчика: (жирная часть ниже добавляется переводчиком, а не содержание оригинальной книги)
Чтобы облегчить понимание этой части контента, вы можете изменить код автора, чтобы он мог фактически работать:
Кода -копия выглядит следующим образом:
var -интервал = 1000;
setInterval (function () {
(функция my_async_function () {
settimeout (function () {
console.log ("1");
}, 5000);
}) ();
}, интервал);
Запустите этот код, и вы обнаружите, что после 5 секунд «Hello» выводит каждые 1 секунду. Мы ожидаем, что после того, как текущая my_async_function была выполнена (взято 5 секунд), подождите 1 секунду, прежде чем выполнить следующую my_async_function, и интервал между каждым выходом должен составлять 6 секунд. Этот результат заключается в том, что my_async_function не выполняется последовательно, но выполняется одновременно.
Следовательно, вам нужен способ установить интервал между концом выполнения MY_ASYNC_FUNCTION и началом выполнения следующей MY_ASYNC_FUNCTION именно то время, указанное в интервальной переменной. Вы можете сделать это:
Кода -копия выглядит следующим образом:
var -интервал = 1000; // 1 секунда
(Function Grade () {// Строка 3
settimeout (function do_it () {
my_async_function (function () {// строка 5
console.log ('async сделан!');
расписание();
});
}, интервал);
} ()); // строка 10
В предыдущем коде объявляется функция, называемая графиком (строка 3), и ее называют сразу после объявления (строка 10). Функция графика будет выполнять функцию do_it через 1 секунду (указан в интервале). Через 1 секунду будет вызвана функция my_async_function в строке 5. Когда он будет выполнен, он вызовет свою собственную анонимную функцию обратного вызова (строка 6). Эта анонимная функция обратного вызова снова сбросит план выполнения DO_IT и позволит ее выполнить снова через 1 секунду, так что код начнет последовательно и непрерывно выполнять.
краткое содержание
Вы можете использовать функцию settimeout () для предварительного установки плана выполнения функции и отменить ее с помощью функции cleartimeout (). Вы также можете использовать setInterval () для периодического выполнения определенной функции. Соответственно, вы можете использовать ClearInterval () для отмены этого повторяющегося плана выполнения.
Если цикл событий заблокирован с использованием чувствительной к процессору операции, функции, которые первоначально планировались выполнять, будут отложены и никогда не будут выполняться. Так что не используйте чувствительные к процессору операции в рамках цикла событий. Кроме того, вы можете использовать процесс.
При использовании ввода/вывода и setInterval () вы не можете гарантировать, что в любой момент времени есть только один ожидающий вызов, но вы можете использовать рекурсивные функции и функции setTimeout (), чтобы избежать этой сложной проблемы.