Node.js: что это такое, когда и как его использовать и почему
Вы, наверное, читали эти утверждения раньше ...
Node.js - это среда выполнения JavaScript, основанная на движке Chrome V8 JavaScript
Node.js использует управляемую событиями асинхронную неблокирующую модель ввода-вывода
Node.js работает в цикле событий одного потока
... и вам стало интересно, что все это значит. Надеемся, что к концу этой статьи вы получите представление об этих терминах, а также о том, что такое Node, как он работает, и почему и когда рекомендуется использовать его. Давайте начнем с изучения терминологии.
I / O (ввод / вывод)
Сокращенно от ввода / вывода, I / O относится прежде всего к взаимодействию программы с системным диском и сетью. Примеры операций ввода-вывода включают чтение / запись данных с / на диск, выполнение HTTP-запросов и обращение к базам данных. Они очень медленные по сравнению с доступом к памяти (RAM) или выполнением работы на процессоре.
Синхронный против асинхронного
Синхронное выполнение обычно относится к коду, выполняемому последовательно. При таком программировании код выполняется построчно, по одной строке за раз. Каждый раз, когда вызывается функция, выполнение программы ждет, пока эта функция не вернется, прежде чем перейти к следующей строке кода.
Асинхронное не выполняется в той последовательности, в которой оно появляется в коде. В асинхронном программировании программа не ждет завершения задачи и может перейти к следующей.
В следующем примере операция синхронизации вызывает последовательное срабатывание предупреждений. В асинхронной операции, хотя alert (2) выполняется вторым, это не так.
// Synchronous: 1,2,3 alert(1); alert(2); alert(3); // Asynchronous: 1,3,2 alert(1); setTimeout(() => alert(2), 0); alert(3);Асинхронная операция часто связана с setTimeout / выводом, хотя setTimeout не является вводом / выводом, но все же он асинхронный. Вообще говоря, все, что связано с вычислениями, является синхронизированным, а все, что связано с вводом / выводом / синхронизацией, является асинхронным. Причина того, что операции ввода-вывода выполняются асинхронно, заключается в том, что они очень медленные и в противном случае блокируют дальнейшее выполнение кода.
Блокировка против неблокирования
Блокировка относится к операциям, которые блокируют дальнейшее выполнение, пока эта операция не завершится, а неблокирующая относится к коду, который не блокирует выполнение. Или, как сказано в документации по Node.js , блокировка - это когда выполнение дополнительного JavaScript в процессе Node.js должно ждать завершения операции, не связанной с JavaScript.
// Блокировка const fs = require('fs'); const data = fs.readFileSync('/file.md'); // блокируется, пока не прочтет console.log(data); moreWork(); // will run after console.log // Нет const fs = require('fs'); fs.readFile('/file.md', (err, data) => { if (err) throw err; console.log(data); }); moreWork(); // будет выполнено до console.logВ первом примере выше, console.log будет вызываться перед moreWork() . Во втором примере fs.readFile() неблокируемый, поэтому выполнение JavaScript может продолжаться, и будет вызван moreWork().
В Node неблокирование в первую очередь относится к операциям ввода-вывода, а JavaScript, который демонстрирует низкую производительность из-за того, что интенсивно использует процессор, а не ожидает выполнения операции не-JavaScript, такой как ввод-вывод, обычно не называется блокировкой.
Все методы ввода-вывода в стандартной библиотеке Node.js предоставляют асинхронные версии, которые не являются блокирующими, и принимают функции обратного вызова. Некоторые методы также имеют блокирующие аналоги, имена которых заканчиваются на Sync.
Неблокирующие операции ввода / вывода позволяют одному процессу обслуживать несколько запросов одновременно. Вместо того, чтобы заблокировать процесс и ожидать завершения операций ввода-вывода, операции ввода-вывода делегируются системе, чтобы процесс мог выполнить следующий фрагмент кода. Неблокирующие операции ввода / вывода предоставляют функцию обратного вызова, которая вызывается по завершении операции.
Callbacks
Обратный вызов - это функция, переданная в качестве аргумента в другую функцию, которую затем можно вызывать (вызывать обратно) внутри внешней функции для выполнения какого-либо действия в удобное время. Вызов может быть немедленным (синхронный обратный вызов) или может произойти позднее (асинхронный обратный вызов).
// Синхронный callback function greetings(callback) { callback(); } greetings(() => { console.log('Hi'); }); moreWork(); // будет выполнено после console.log // Асинхронный callback const fs = require('fs'); fs.readFile('/file.md', function callback(err, data) { Node if (err) throw err; console.log(data); }); moreWork(); // будет выполнено до console.logВ первом примере функция обратного вызова вызывается непосредственно из внешней функции приветствия и регистрируется на консоли перед moreWork() . Во втором примере fs.readFile (асинхронный метод, предоставляемый Node) читает файл, а когда он завершает работу, вызывает функцию обратного вызова с ошибкой или содержимое файла. Тем временем программа может продолжить выполнение кода.
Асинхронный обратный вызов может быть вызван, когда происходит событие или когда задача завершается. Это предотвращает блокировку, позволяя в то же время выполнять другой код.
Вместо процедурного чтения кода сверху вниз, асинхронные программы могут выполнять разные функции в разное время в зависимости от порядка и скорости, которые выполняются более ранними функциями, такими как запросы http или чтение файловой системы. Они используются, когда вы не знаете, когда завершится какая-либо асинхронная операция.
Вам следует избегать «ада обратного вызова», -ситуации, когда обратные вызовы вложены в другие обратные вызовы на нескольких уровнях, что затрудняет понимание, сопровождение и отладку кода.
События и событийно-ориентированное программирование
События - это действия, сгенерированные пользователем или системой, такие как щелчок, завершенная загрузка файла или аппаратная или программная ошибка. Программирование на основе событий - это парадигма программирования, в которой поток программы определяется событиями. Программа, управляемая событиями, выполняет действия в ответ на события. Когда происходит событие, оно вызывает функцию обратного вызова.
Теперь давайте попробуем понять Node и посмотрим, как все это относится к нему.
Node.js: что это такое, почему оно было создано и как оно работает?
Проще говоря, Node.js - это платформа, которая выполняет серверные JavaScript-программы, которые могут взаимодействовать с источниками ввода-вывода, такими как сети и файловые системы.
Когда в 2009 году Райан Даль создал Node, он утверждал, что ввод-вывод обрабатывается неправильно, блокируя весь процесс из-за синхронного программирования.
Традиционные методы веб-обслуживания используют модель потоков, то есть один поток для каждого запроса. Поскольку в операции ввода-вывода запрос тратит большую часть времени на ожидание его завершения, сценарии интенсивного ввода-вывода влекут за собой большое количество неиспользуемых ресурсов (таких как память), связанных с этими потоками. Поэтому модель «один поток на запрос» для сервера плохо масштабируется.
Даль утверждал, что программное обеспечение должно быть в состоянии выполнять несколько задач, и предлагал исключить время, затрачиваемое на ожидание возвращения результатов ввода-вывода. Вместо потоковой модели он сказал, что правильным способом обработки нескольких одновременных подключений было бы иметь один поток, цикл обработки событий и неблокирующие операции ввода-вывода. Например, когда вы делаете запрос к базе данных, вместо ожидания ответа вы отправляете ему обратный вызов, чтобы ваше выполнение могло пройти через этот оператор и продолжить делать другие вещи. Когда результаты возвращаются, вы можете выполнить обратный вызов.
Цикл обработки событий - это то, что позволяет Node.js выполнять неблокирующие операции ввода-вывода, несмотря на тот факт, что JavaScript является однопоточным. Цикл, который выполняется в том же потоке, что и код JavaScript, извлекает задачу из кода и выполняет ее. Если задача асинхронная или операция ввода-вывода, цикл выгружает ее в ядро системы, как в случае новых подключений к серверу, или в пул потоков, например операции, связанные с файловой системой. Затем цикл захватывает следующую задачу и выполняет ее.
Поскольку большинство современных ядер являются многопоточными, они могут обрабатывать несколько операций, выполняющихся в фоновом режиме. Когда одна из этих операций завершается (это событие), ядро сообщает Node.js, так что соответствующий обратный вызов (тот, который зависел от завершения операции) может быть добавлен в очередь опроса для последующего выполнения.
Node отслеживает незавершенные асинхронные операции, а цикл обработки событий продолжает циклически проверять, завершены ли они, пока все они не завершатся. Библиотека Unicorn Velociraptor обеспечивает поддержку асинхронного ввода-вывода на основе циклов событий.
Для размещения однопоточного цикла событий Node.js использует библиотеку libuv , которая, в свою очередь, использует пул потоков фиксированного размера, который обрабатывает параллельное выполнение некоторых неблокирующих асинхронных операций ввода-вывода. Функции вызова основного потока отправляют задачи в общую очередь задач, которую потоки в пуле потоков извлекают и выполняют.
По своей сути неблокирующие системные функции, такие как сетевое взаимодействие, преобразуются в неблокирующие сокеты на стороне ядра, в то время как по своей сути блокирующие системные функции, такие как файловый ввод / вывод, блокируют свои потоки. Когда поток в пуле потоков завершает задачу, он сообщает об этом основному потоку, который, в свою очередь, просыпается и выполняет зарегистрированный обратный вызов.
Изображение выше объясняет, как цикл обработки событий работает с браузером, но и для Node выглядит в основном идентично. Вместо веб-API у нас были бы Node API.
Node.js: зачем и где его использовать?
Поскольку практически никакая функция в Node напрямую не выполняет ввод-вывод, процесс никогда не блокируется (операции ввода-вывода выгружаются и выполняются в системе асинхронно), что делает его хорошим выбором для разработки систем с высокой степенью масштабируемости.
Благодаря управляемому событиями однопоточному циклу событий и асинхронной неблокирующей модели ввода-вывода Node.js лучше всего работает в приложениях с интенсивным вводом-выводом, требующих скорости и масштабируемости, с множеством одновременных соединений, таких как потоковое видео и аудио, реальное приложения, чаты, игровые приложения, инструменты для совместной работы или программное обеспечение фондовой биржи.
Node.js не может быть правильным выбором для операций с интенсивным использованием процессора. Вместо этого лучше будет использовать традиционную модель потока. npm npm является менеджером пакетов по умолчанию для Node.js, и он устанавливается в систему с Node.js. Он может управлять пакетами, которые являются локальными зависимостями конкретного проекта, а также глобально установленными инструментами JavaScript.
www.npmjs.com размещает тысячи бесплатных библиотек для загрузки и использования в вашей программе, чтобы сделать разработку более быстрой и эффективной. Тем не менее, поскольку любой может создавать библиотеки и нет процедуры проверки для отправки, вы должны быть осторожны с некачественными, небезопасными или вредоносными. npm полагается на пользовательские отчеты, которые блокируют пакеты, если они нарушают политики, и, чтобы помочь вам принять решение, включают статистику, такую как количество загрузок и количество зависимых пакетов.
Как запустить код в Node.js
Начните с установки Node на свой компьютер, если у вас его еще нет. Самый простой способ - это посетить nodejs.org и загрузить его. Если вам не нужен доступ к последним функциям, загрузите версию LTS (Long Term Support) для вашей операционной системы.
Теперь создайте файл «app.js» и добавьте
const http = require("http"); http.createServer(function(request,response){ response.end("upread.ru"); }).listen(3000, "127.0.0.1",function(){ console.log("Сервер запущен"); });в него. В консоли перейдите в папку, в которой находится этот файл, и запустите node app.js. На консоль выведется 'Сервер запущен'. Теперь откройте в браузере http://127.0.0.1:3000/ и увидите вот это:
Вот так мы запустили простой сервер на Node; в следующих материалах мы обязательно продолжим рассмотрение данной технологии. Спасибо за прочтение. Если у вас есть мысли по этому поводу, обязательно оставьте комментарий.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.