Прежде чем говорить о Event Loop (цикле событий), давайте разберемся с узлом, чтобы лучше понять, что делает цикл событий.
Что такое узел
Node.js — это среда выполнения JavaScript, основанная на движке Chrome V8. Node — это не язык. Он позволяет запускать js на серверной части. Среда выполнения не включает полный набор js, поскольку DOM и BOM не включены в Node также предоставляет некоторые новые модули, такие как http, fs и другие модули.
что решает узел
Основная цель Node — предоставить простой инструмент разработки для создания высокопроизводительных серверов. Узким местом веб-сервера является количество одновременных пользователей, если сравнивать реализацию Java и Php.
Node имеет очевидные преимущества в производительности при работе с сценариями с высоким параллелизмом и интенсивным вводом-выводом.
- Высокий параллелизм относится к одновременному доступу к серверу в одно и то же время.
- Интенсивный ввод-вывод относится к операциям с файлами, сетевыми операциями и базами данных и относительно интенсивно использует процессор.
Основным сценарием сети является получение запросов от клиентов на чтение статических ресурсов и отрисовку интерфейса, поэтому Node очень подходит для разработки веб-приложений.
процесс и поток
Процесс – это основная единица операционной системы для распределения ресурсов и планирования задач. Поток – это одноразовая единица выполнения программы, созданная на основе процесса. Процесс может иметь несколько потоков.
- поток браузера
- Пользовательский интерфейс — включает адресную строку, кнопки «вперед/назад», меню закладок и т. д.
- Механизм браузера — передает инструкции между пользовательским интерфейсом и механизмом рендеринга (основной процесс браузера).
- Механизм рендеринга, также известный как ядро браузера (процесс рендеринга в браузере).
- Один плагин соответствует одному процессу (процесс стороннего плагина)
- GPU улучшает работу в Интернете (процесс GPU)
- движок браузерного рендеринга
- Механизм рендеринга является многопоточным внутри, включая потоки пользовательского интерфейса и потоки js.
- js thread ui thread Эти два потока являются взаимоисключающими, цель состоит в том, чтобы гарантировать отсутствие конфликта.
- Поток пользовательского интерфейса поместит изменения в очередь. Когда поток js простаивает, поток пользовательского интерфейса продолжит рендеринг
- js один поток
- js однопоточный, почему? Какая страница не будет загромождена, если несколько потоков одновременно работают с DOM? Так называемый одиночный поток здесь означает, что основной поток является однопоточным, поэтому основной поток в Node по-прежнему является однопоточным.
- веб-воркер многопоточность
- Он не на том же уровне, что и основной поток js.Основной поток может управлять веб-воркером, но веб-воркер не может работать с DOM и не может получать документы и окна.
- другие темы
- Поток триггера события браузера (используется для управления циклом событий, хранения функций обратного вызова setTimeout, событий браузера и ajax)
- Поток триггера синхронизации (поток, в котором находится таймер setTimeout)
- Поток асинхронного запроса HTTP (поток запроса ajax)
Однопоточная функция экономит память и не требует переключения контекстов выполнения. И один поток не должен управлять проблемой блокировок, так называемые блокировки имеют только понятие блокировки в java, поэтому нам не нужно их подробно изучать.
Цикл событий в браузере
- Задачи синхронизации выполняются в основном потоке, образуя стек выполнения.
- В дополнение к основному потоку существует также очередь задач. Как только асинхронная задача получает результат выполнения, событие помещается в очередь задач.
- Как только все задачи синхронизации в стеке выполнения будут выполнены, система прочитает очередь задач, поместит события из очереди в стек выполнения и последовательно выполнит их.
- Основной поток считывает события из очереди задач, что является непрерывным циклом.
Весь этот рабочий механизм также называется Event Loop (цикл событий).
Цикл событий в узле
Как показано на картинке (изображение для справки):
* Код, который мы напишем, будет передан движку V8 для обработки * В коде может быть вызван nodeApi, и узел будет передан в библиотеку LIBUV для обработки * LIBUV реализует асинхронный ввод-вывод, блокируя ввод-вывод и многопоточность. * В зависимости от событий результаты помещаются в очередь событий и, наконец, передаются нашему приложению.синхронный, асинхронный блокирующий и неблокирующий
- Блокирующие и неблокирующие относятся к состоянию вызывающей стороны, фокусируясь на состоянии программы во время ожидания результата вызова.
- Синхронные и асинхронные относятся к тому, как уведомляется вызываемый объект, с упором на механизм уведомления о сообщениях.
Макрозадачи и микрозадачи
- макрозадача:
- setTimeout, setInterval, setImmediate, I/O
- микрозадача:
- process.nextTick,
- Нативные промисы (некоторые реализованные промисы помещают метод then в макрозадачи, а браузеры по умолчанию помещают их в микрозадачи),
- Object.observe (устарело),
- MutationObserver (несовместим, устарел)
- MessageChannel (принцип реализации nextTick в vue)
Синхронный код выполняется первым, а выполнение выполняется в стеке.Микрозадачи больше, чем макрозадачи.Микрозадачи будут выполняться первыми (стек), а макрозадачи будут выполняться (очередь).
Говоря об этом, введите несколько строк кода, чтобы обобщить знания, о которых мы упоминали выше.
《1》Макрозадачи, микрозадачи выполняются в разном порядке в среде браузера и узла
// 这个列子里面,包含了宏任务,微任务,分别看看浏览器和node 打印的结果
console.log(1)
// 栈
setTimeout(function(){
console.log(2)
// 微任务
Promise.resolve(100).then(function(){
console.log('promise')
})
})
// 栈
let promise = new Promise(function(resolve, reject){
console.log(7)
resolve(100)
}).then(function(data){
// 微任务
console.log(data)
})
// 栈
setTimeout(function(){
console.log(3)
})
console.log(5)
// 浏览器结果:1 7 5 100 2 promise 3
// node 结果: 1 7 5 100 2 3 promise
Порядок выполнения браузера и среды узла разный: браузер сначала выполняет стек и микрозадачи в стеке, а затем переходит к следующему стеку. В среде узла микрозадача выполняется только после завершения стека.
«2» setTimeout setImmediate — это все задачи макросов, кто будет выполнять их первым?
setTimeout(function(){
console.log('timeout')
})
setImmediate(function(){
console.log('setImmediate')
})
// 结果打印:timeout setImmediate
setTimeout setImmediate эти два зависят от времени выполнения узла
"3" nextTick, а затем обе микрозадачи, кто выполнит их первым?
process.nextTick(function(){
console.log('nextTick')
})
Promise.resolve().then(function(){
console.log('then')
})
// 结果打印:nextTick then
// 再加一个宏任务呢
setImmediate(function(){
console.log('setImmediate')
})
// 结果打印:nextTick then setImmediate
nextTick будет выполняться быстрее, чем другие микрозадачи и макрозадачи
"4" файловая операция ввода/вывода (макрозадача), с микрозадачей, кто выполнит ее первым?
let fs = require('fs');
fs.readFile('./1/log',function(){
console.log('fs')
})
process.nextTick(function(){
console.log('text')
})
// 结果打印:text fs
файловая операция ввода/вывода (макрозадача), если есть микрозадача, сначала выполнить микрозадачу, а затем выполнить чтение файла