Я все больше вникаю во внутреннее устройство архитектуры Node.js, и термин, который я часто вижу, - это «тик», как «следующий тик цикла событий» или функция nextTick () .
Чего я не видел, так это четкого определения того, что такое «галочка». Основываясь на различных статьях ( например, этой ), я смог собрать в голове концепцию, но не уверен, насколько она точна.
Могу ли я получить точное и подробное описание тика цикла событий Node.js?
Ответы:
Помните, что хотя JavaScript является однопоточным, весь ввод-вывод узла и вызовы собственных API-интерфейсов либо асинхронны (с использованием механизмов, зависящих от платформы), либо выполняются в отдельном потоке. (Все это делается через libuv.)
Поэтому, когда в сокете доступны данные или возвращается собственная функция API, нам нужен синхронизированный способ вызова функции JavaScript, которая заинтересована в конкретном событии, которое только что произошло.
Небезопасно просто вызывать функцию JS из потока, в котором произошло собственное событие, по тем же причинам, с которыми вы столкнетесь в обычном многопоточном приложении - условия гонки, неатомарный доступ к памяти и т. Д.
Итак, что мы делаем, так это помещаем событие в очередь потокобезопасным способом. В упрощенном псевдокоде это примерно так:
Затем, возвращаясь к основному потоку JavaScript (но на стороне C), мы делаем что-то вроде:
while (true) { // this is the beginning of a tick lock (queue) { var tickEvents = copy(queue); // copy the current queue items into thread-local memory queue.empty(); // ..and empty out the shared queue } for (var i = 0; i < tickEvents.length; i++) { InvokeJSFunction(tickEvents[i]); } // this the end of the tick }
while (true)
(Который фактически не существует в исходном коде узла, это чисто иллюстративный) представляет собой цикл событий . Внутреннийfor
вызов вызывает функцию JS для каждого события, находящегося в очереди.Это галочка: синхронный вызов нуля или более функций обратного вызова, связанных с любыми внешними событиями. Как только очередь опустеет и последняя функция вернется, тик закончится. Мы возвращаемся к началу (следующий тик) и проверяем события, которые были добавлены в очередь из других потоков во время работы нашего JavaScript .
Что можно добавлять в очередь?
process.nextTick
setTimeout
/setInterval
fs
,net
и так далее)crypto
функции, интенсивно использующие процессор, такие как криптопотоки, pbkdf2 и PRNG (которые на самом деле являются примером ...)источник
setImmediate
также будет добавлена функция.Более простой ответ для новичков в JavaScript:
Первое, что нужно понять, это то, что JavaScript - это «однопоточная среда». Это относится к поведению JavaScript при выполнении ваших блоков кода по одному из «цикла событий» в одном потоке. Ниже представлена простая реализация цикла событий, взятая из книги Кайла Симпсона ydkJS, а затем объяснение:
// `eventLoop` is an array that acts as a queue (first-in, first-out) var eventLoop = [ ]; var event; // keep going "forever" while (true) { // perform a "tick" if (eventLoop.length > 0) { // get the next event in the queue event = eventLoop.shift(); // now, execute the next event try { event(); } catch (err) { reportError(err); } } }
Первый цикл while имитирует цикл событий. Тик - это исключение события из «очереди цикла событий» и выполнение указанного события.
См. Ответ «Josh3796» для более подробного объяснения того, что происходит при удалении из очереди и выполнении события.
Также я рекомендую прочитать книгу Кайла Симпсона тем, кто заинтересован в глубоком понимании JavaScript. Он полностью бесплатный и с открытым исходным кодом, его можно найти по этой ссылке: https://github.com/getify/You-Dont-Know-JS.
Конкретный раздел, на который я ссылался, можно найти здесь: https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/sync-async/ch1.md
источник
Очень простой и короткий способ установки тика Event Loop:
Он используется внутренним механизмом узла, где при обработке набора запросов в очереди запускается тик, который представляет собой завершение задачи.
источник