Node.js Flashcards

1
Q

Отличия Node от браузера

A

Браузер:
Интерактивные веб-приложения
DOM, Window…
Нужно поддерживать старые версии браузеров
ES модули

Node:
Серверные приложения
API файловой системы, сети, криптографии…
Единная версия Node на сервере
CommonJS + ES модули

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

REPL

A

Read Eval Print Loop
Режим для отладки
Для входа в него пишем “node”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Модуль FS

A

Модуль файловой системы, возвращает буффер

readFileSync(path) - синхронно читает файл

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Зачем нужны модули?

A

Изоляция
Организация файловой системы
Переиспользование

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

История модулей

A

1) IIFE
(const a = 2; APP.number = a)()
Работает только в браузере

2) require
module.exports = {a, b}
const {a,b} = require(some.js)
Работает только в Node, а в бразуере используется только для сборки. Webpack на самом деле собирает тоже всё на Node

3) ES модули
export
import

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Отличия CommonJS от ES модулей

A

CommonJS Модули:
1) Require в пишем любом месте
2) Можно использовать в условиях
3) Загружает весь модуль, даже если импортируем небольшую часть
4) Синхронная загрузка модуля, может заблокировать поток

ES Модули:
1) Импорты всегда должны быть на верхнем уровне
2) Нельзя использовать в условиях (кроме асинхронных)
3) Выборочно загружает части их модуля
4) Асинхронная загрузка модуля

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Как использовать ES модули в Node?

A

1) Работать с .mjs файлами
2) В package.json писать type: “module”
3) Передать node аргумент –input-type=module

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Глобальные переменные

A

global - рутовый объект

console
performance
Buffer
AbortController
queueMicrotask
WebAssembly

setTimeout
setInterval
setImmediate
clearTimeout
clearInterval
clearImmediate

URL
URLSearchParams

MessageChannel
MessageEvent
MessagePort

Event
EventTarget

TextDecoder
TextEncoder

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Модульные переменные

A

__dirname
__filename
exports - это алиас для module.exports
module
require()

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Отличия Event Emitter от Event Target

A

Event Emitter (предпочтительнее для использования)
Берется из модуля events
Несколько lisener на 1 событие
Полностью эмулирует Event Emitter из браузера
Обработка ошибок через error
Встроенные события add / remove listeners

Event Target
Глобальная переменная
Только 1 listener на событие
Частично эмулирует API браузера
Нет обработки через error
Нет событий добавления и удаления обработчиков

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Какие методы есть в Event Emitter

A

addListener - подписаться
on - подписаться
removeListener - отписаться
off - отписаться

prependListener - добавит листенер в начало очереди эмиттера, и его событие выполнится раньше всех (по дефлоту выполняется в порядке очереди добавления)
prependOnceListener - то же самое что и prependListener, но после выполнения удаляет листенер из эмиттера

removeAllListeners - отписаться от всех листенеров
emit - выполнить событие
once - после первого выполнения событие будет удалено из эмиттера

setMaxListeners - устанавливает максммальное количество листенеров для эмиттера, по дефолту их 10
listenerCount - узнать сколько листенеров находится на одном ивенте
listeners - показывает какие именно функции висят на событии
eventNames - показывает именна событий, которые сейчас повешены на эмиттер

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Какие методы есть в Event Target

A

addEventListener - повесить обработчик
dispatchEvent - выполнить событие, но в качестве аргумента должен быть new Event(“name”), а не просто строка

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

С10K проблема

A

В мультитредовых серверах, например на Java, раньше 1 поток (1 поток обслуживал 1 запрос на сервер) примерно занимал 1мб, 10000 потоков - 10 ГБ памяти

Эта проблема была раньше, сейчас же трудности с обработкой например миллиона запросов, так как на это на сервере должно быть 1 ТБ оперативной памяти

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Сколько потоков в Node.js?

A

1 поток и огромный thread pool

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Non blocking I/O

A

Главный поток не блокируется вводом и выводом
Сервер будет продолжать обслуживать запросы
Мы работаем с асинхронным кодом

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Event Loop

A

1) Сначала делается запрос
2) Начинает обрабываться нашим V8
3) Проходит через Node bindings и превращается в C/C++ если надо
4) Потом попадает в Event Queue если это асинхронная операция
5) Если синхронный код, то он попадает сразу в Callstack,
6) Асинхронные операции, которые попали в Callstack, если блокируют поток, то попадают в Worker threads, а отттуда снова в event queue, но только как callback

ФАЗЫ:
0) Выполняется синхронный код
1) timers - смотрит есть ли таймеры которые должны завершиться
2) pending callbacks - коллбеки от системных операций
3) idle, prepare - внутрення фаза реализации libuv, повлиять на неё мы никак не можем
4) poll - обработка собтий i/o (читаем файл, записываем и т.д), читает не все запросы, а только какое-то время, и потом снова возвращается по циклу к этому пункту
5) check - тут только setImmediate
6) close callbacks - будут обработаны все close callbacks, например прервалось соединение с сокетами.
7) exit check

!!! Между каждой фазой вызываются промисы, и process.nextTick()

17
Q

Что такое setImmediate и какие аргументы принимает?

A

Отрабатывает сразу после выполнения синхронного кода, примает только функцию. P.S. это не таймер

18
Q

Как мгновенно отвязать и привязать id таймера

A

someTimerId.unref()
someTimerId.ref()

Очень редкий кейс применения

19
Q

Сколько Working Threads в Node?

A

По умолчанию 4
Можно увеличить до 1024
Раньше было до 128

Это всё ограничения libuv
Каждый тред работает на 1 ядре процессора

20
Q

Модуль Crypto

A

Позволяет работать с шифрованием

pbkdf2 - асинхронно позволяет создать из пароля хеш строку

21
Q

Как увеличить количество Working Threads ?

A

process.env.UV_THREADPOOL_SIZE =

22
Q

Что работает на Working Threads а что на уровня ядра?

A

Working Threads:
Все файловые операции fs.*
dns.lookup
Pipes (некоторые случаи)
CPU intense tasks

Системные асинхронные выховы на уровне ядра:
TCP/UDP сервер и клиент
Pipes
DNS Resolve
Child process

23
Q

Модуль https

A

Дает возможность делать запросы по https

24
Q

Как измерять performance в Node?

A

1) Если нужно измеритиь кусочек кода:
Сначала ставим метки внутри функции или кода:
performance.mark(“start”)
performance.mark(“end”)

Потом ставим отметку измерения
performance.measure(“some name”, “start”, “end”)

После импортируем перфморманс хук:
const perf_hooks = require(‘perf_hooks’);

Создаем обсервер перформанса из хука:
const performanceObserver = new perf_hooks.PerformanceObserver((items, observer) => {
const entry = items.getEntriesByName(“name of our метка измерения”)[0];
console.log(777, “entry: “, entry);
observer.disconnect();
})

Вызываем обсервер:
performanceObserver.observe({ entryTypes: [“measure”] });

2) Если нужно померять целую функцию, то можем метки не раставлять, а сделать так:

Обернуть нашу функцию в timerify
slow = perf_hooks.performance.timerify(slow);

Вызвать обсервер с entryType: function
performanceObserver.observe({ entryTypes: [“function”] });

25
Q

Как работать с worker_threads

A

Worker Threads это аналог WebWorker из браузера
1) Для воркера нужо создать отдельный файл

2) Импортируем const { parentPort, workerData } = require(“worker_threads”)

3) parentPort.postMessage(compute(workerData)) - compute это наша функция рандомная

4) В файле где используем воркер импортируем:
const { Worker } = require(“worker_threads”)

5) И делаем примерно такое:
const compute = (array) => {
return new Promise((resolve, reject) => {
const worker = new Worker(“./worker.js”, {
workerData: {array}
})

    worker.on("message", (msg) => resolve(msg))
    worker.on("error", (err) => reject(err.name))
    worker.on("exit", () => console.log("end"))
}) }

Важно: Плохая идея использовать новый воркер на каждый новый запрос, тем самым тебя могут задэдосить

26
Q

Что такое spawn?

A

Когда использовать:
Когда вам нужно запустить команду, которая может долго работать и выводить много данных.

Как работает:
spawn запускает команду и позволяет вам читать ее вывод по мере выполнения. Это очень полезно для работы с большими объемами данных или долгосрочными процессами, так как не ограничивает объем вывода.

Пример:
Если нужно запустить команду и обрабатывать ее вывод построчно, как это делают программы ping или tail -f.

const { spawn } = require(‘child_process’);

const child = spawn(‘ls’, [‘-lh’, ‘/usr’]); // Запуск команды ‘ls -lh /usr’

child.stdout.on(‘data’, (data) => {
console.log(stdout: ${data});
});

child.stderr.on(‘data’, (data) => {
console.error(stderr: ${data});
});

child.on(‘close’, (code) => {
console.log(child process exited with code ${code});
});

27
Q

Что такое exec?

A

Когда использовать:
Когда вам нужно запустить команду и получить весь ее вывод разом, после завершения выполнения.

Как работает:
exec запускает команду и сохраняет весь ее вывод (stdout и stderr) в буфере. После завершения выполнения команды вы получаете весь вывод сразу. Это удобно для коротких команд с небольшим объемом вывода.

Пример:
Если нужно выполнить команду и получить результат целиком, например cat для чтения небольшого файла или ls для краткого списка файлов.

const { exec } = require(‘child_process’);

exec(‘ls -lh /usr’, (error, stdout, stderr) => {
if (error) {
console.error(exec error: ${error});
return;
}
console.log(stdout: ${stdout});
console.error(stderr: ${stderr});
});

28
Q

Чем отличаются fork, spawn и exec от worker_threads?

A

Лучше всегда использовать woker, так как это современный подход. Раньше в Node был только fork. Произовдительность в woker при передаче больших файлов намного выше. Все новые библиотеки переписываются с fork на worker threads

fork, spawn и exec:
Создают отдельные процессы с полной изоляцией.
Используются для выполнения внешних команд и скриптов, например написанных не на JS.
Процессы не делят память, что делает их более защищенными, но менее эффективными в обмене данными.

worker_threads:
Создают потоки внутри одного процесса.
Используются для параллельных вычислений на JavaScript с быстрым обменом данными.
Потоки делят память, что позволяет эффективный и быстрый обмен данными, но требует осторожности для предотвращения проблем с доступом к общей памяти.

29
Q

Что такое fork?

A

Создет отдельный процесс

Основные отличия и преимущества fork над spawn и exec:

IPC (Inter-Process Communication):

fork автоматически устанавливает канал для межпроцессного взаимодействия (IPC) между родительским и дочерним процессами. Это упрощает обмен сообщениями.

spawn также может быть использован для создания дочерних процессов, но настройка канала IPC и обмен сообщениями требует дополнительных усилий и кода.

Оптимизация для Node.js:

fork специально оптимизирован для запуска новых процессов Node.js. Он автоматически наследует родительские переменные окружения и позволяет легко управлять выполнением Node.js скриптов.

spawn более универсален и используется для запуска любых команд или скриптов. Хотя он может запускать Node.js процессы, fork делает это более эффективно и с меньшими усилиями для разработчика.