Помните, что хотя JavaScript является однопоточным, весь ввод-вывод узла и вызовы собственных API-интерфейсов либо асинхронны (с использованием механизмов, зависящих от платформы), либо выполняются в отдельном потоке. (Все это делается через libuv.)
Поэтому, когда в сокете доступны данные или возвращается собственная функция API, нам нужен синхронизированный способ вызова функции JavaScript, которая заинтересована в конкретном событии, которое только что произошло.
Небезопасно просто вызывать функцию JS из потока, в котором произошло собственное событие, по тем же причинам, с которыми вы столкнетесь в обычном многопоточном приложении - условия гонки, неатомарный доступ к памяти и т. Д.
Итак, что мы делаем, так это помещаем событие в очередь потокобезопасным способом. В упрощенном псевдокоде это примерно так:
lock (queue) {
queue.push(event);
}
Затем, возвращаясь к основному потоку JavaScript (но на стороне C), мы делаем что-то вроде:
while (true) {
lock (queue) {
var tickEvents = copy(queue);
queue.empty();
}
for (var i = 0; i < tickEvents.length; i++) {
InvokeJSFunction(tickEvents[i]);
}
}
while (true)
(Который фактически не существует в исходном коде узла, это чисто иллюстративный) представляет собой цикл событий . Внутренний for
вызов вызывает функцию JS для каждого события, находящегося в очереди.
Это галочка: синхронный вызов нуля или более функций обратного вызова, связанных с любыми внешними событиями. Как только очередь опустеет и последняя функция вернется, тик закончится. Мы возвращаемся к началу (следующий тик) и проверяем события, которые были добавлены в очередь из других потоков во время работы нашего JavaScript .
Что можно добавлять в очередь?
process.nextTick
setTimeout
/setInterval
- Ввод / вывод (материал , из
fs
, net
и так далее)
crypto
функции, интенсивно использующие процессор, такие как криптопотоки, pbkdf2 и PRNG (которые на самом деле являются примером ...)
- любые собственные модули, которые используют рабочую очередь libuv, чтобы синхронные вызовы библиотеки C / C ++ выглядели асинхронными