Backend Ready | IT
8.31K subscribers
1.25K photos
93 videos
6 files
1K links
По всем вопросам: @AdilNow
Download Telegram
Forwarded from Исходный Код
Смоделировали задачу с двумя ++ для разработчиков!

🔥 Ситуация:
Запускаем модуль выплат для e-commerce. Использовали стандартную схему с Webhooks от платежного шлюза. Локально все летает, автотесты подтверждают идемпотентность.


📊 После релиза видим аномалию:
У 0.1% юзеров транзакции дублируются. Причем в логах шлюза - два успешных вызова с разницей в 50 мс, а в нашей базе - две записи с разными ID, но одинаковым внешним Correlation ID.


🎮 Задача:
Вам нужно определить ту самую причину в логике бэкенда или БД, которая позволила создать дубль, несмотря на проверку.

🔍
Варианты ответов в карточках!


💬 Если дается сложно: две подсказки оставили в комментариях!

📱 Исходный код — подписаться!
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Исходный Код
Я считаю, что правильный ответ:
Anonymous Quiz
19%
A
13%
B
46%
C
16%
D
6%
E
🛡️ Модуль events — архитектура на основе событий

Node.js построен вокруг событий. Почти всё — от HTTP-серверов до потоков чтения файлов — работает на базе класса EventEmitter. Этот модуль позволяет создавать свои события и строить слабо связанную архитектуру приложения.

events — создание и обработка событий

emit()
on() / once()
removeListener()
eventNames()

emit() — генерирует событие, передавая данные всем подписанным слушателям. Это похоже на крик в рупор: кто слушает, тот среагирует.

const EventEmitter = require('events');
const myEmitter = new EventEmitter();

myEmitter.emit('order_created', { id: 105 });




on() — регистрирует постоянного слушателя. Каждый раз, когда событие случается, вызывается колбэк.
once() — срабатывает только один раз. После первого выполнения слушатель автоматически удаляется. Удобно для одноразовых действий, например, инициализации БД.

myEmitter.on('update', (data) => console.log('Обновлено:', data));
myEmitter.once('start', () => console.log('Запуск системы...'));


removeListener() — отписывает конкретную функцию от события. Это критически важно для предотвращения утечек памяти, если ты динамически создаешь слушателей.
error — это специальное событие. Если ты сделаешь emit('error') и на него никто не подписан, Node.js завершит процесс с ошибкой. Всегда вешай обработчик ошибок!

myEmitter.on('error', (err) => {
console.error('Что-то пошло не так:', err.message);
});


MaxListeners — по умолчанию на одно событие можно повесить не более 10 слушателей. Если нужно больше, используй setMaxListeners(). Это сделано для того, чтобы ты случайно не создал бесконечный цикл подписок.
🌊 Модуль stream — работа с огромными данными без перегрузки RAM

Если тебе нужно прочитать файл размером 10 ГБ на сервере с 2 ГБ оперативки, обычный fs.readFile уронит приложение. Стримы решают эту проблему, передавая данные небольшими кусочками (чанками), как конвейер.

stream — потоковая обработка данных

Readable
Writable
Duplex / Transform
pipeline()

Readable — поток, из которого можно читать. Данные поступают по мере готовности, не забивая память целиком.

const fs = require('fs');
const readable = fs.createReadStream('big_video.mp4');

readable.on('data', (chunk) => {
console.log(`Получено ${chunk.length} байт`);
});




Writable — поток, в который можно записывать. Например, отправка ответа пользователю или запись логов в файл.

const writable = fs.createWriteStream('copy.mp4');
readable.pipe(writable); // Автоматическая перекачка данных


Transform — особый вид потока, который изменяет данные «на лету». Например, можно сжимать текст в Gzip прямо в процессе чтения.

const zlib = require('zlib');
readable.pipe(zlib.createGzip()).pipe(writable);


pipeline() — современный способ объединения потоков. В отличие от .pipe(), он корректно обрабатывает ошибки во всех звеньях цепи и очищает ресурсы, если что-то пошло не так.

const { pipeline } = require('stream/promises');

await pipeline(
fs.createReadStream('file.txt'),
zlib.createGzip(),
fs.createWriteStream('file.txt.gz')
);


Backpressure — механизм, который не дает источнику «затопить» приемник данными, если тот не успевает их обрабатывать. Стримы в Node.js управляют этим автоматически.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
2👎1
200 тыс.₽ сейчас РЕАЛЬНО базовый минимум ⏺️

Который нужен для комфортной жизни в любом месте⤵️

Не знаешь, где словить такой куш?

Удаленка в долларах 💸 — канал для профи из СНГ с вакансиями в стабильной валюте.

IT, маркетинг, дизайн, крипта: ты точно в этом разбираешься

Осталось только начать нормально зарабатывать!

15+ актуальных вакансий за сегодня уже в канале:
https://t.me/+qoCsrhInumQyN2Ni 🔗
Please open Telegram to view this post
VIEW IN TELEGRAM
📦 Модуль cluster — масштабируем приложение на все ядра CPU

Node.js по умолчанию работает в одном потоке. Это значит, что даже на мощном сервере с 16 ядрами ваше приложение будет использовать только одно. Модуль cluster позволяет легко запустить клон вашего приложения на каждом ядре, увеличивая производительность в разы.

cluster — многопоточность для бэкенда

cluster.isPrimary
cluster.fork()
cluster.on('exit')
process.pid

cluster.isPrimary — свойство, которое помогает понять, является ли текущий процесс "главным" (менеджером) или "рабочим" (воркером).

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isPrimary) {
// Мастер-процесс создает воркеры
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
// Рабочие процессы запускают сервер
http.createServer((req, res) => {
res.writeHead(200);
res.end('Hello World');
}).listen(8000);
}




cluster.fork() — создает новый рабочий процесс. Каждый воркер имеет свою память и свой Event Loop, но все они делят один и тот же порт сервера.

Балансировка нагрузки — Master-процесс сам распределяет входящие запросы между воркерами. Если один воркер занят тяжелыми вычислениями, запрос уйдет свободному.

Устойчивость — если один из воркеров упадет из-за ошибки, Master-процесс может это отследить и мгновенно запустить новый экземпляр.

cluster.on('exit', (worker, code, signal) => {
console.log(`Воркер ${worker.process.pid} умер. Запускаю новый...`);
cluster.fork();
});

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Какие http методы могут быть?

HTTP (HyperText Transfer Protocol) методы представляют собой набор стандартных операций, которые используются для взаимодействия между клиентом и сервером в сети. Каждый метод определяет конкретное действие, которое должен выполнить сервер. Вот основные HTTP методы и их предназначение:

🟠GET
Метод GET используется для получения данных с сервера. Он запрашивает представление ресурса, не изменяя его состояния. GET запросы часто используются для запросов веб-страниц и получения данных из API.

🟠POST
Метод POST используется для отправки данных на сервер с целью создания или обновления ресурса. Это может включать отправку формы на веб-сайте или загрузку файла. POST запросы обычно содержат данные в теле запроса.

🟠PUT
Метод PUT используется для обновления существующего ресурса или создания нового ресурса на сервере. Если ресурс уже существует, он будет обновлен, если нет — будет создан.

🟠DELETE
Метод DELETE используется для удаления ресурса с сервера. Запросы DELETE могут быть небезопасными, так как они изменяют состояние сервера, удаляя данные.

🟠PATCH
Метод PATCH используется для частичного обновления ресурса. В отличие от PUT, который заменяет весь ресурс, PATCH изменяет только указанные части ресурса.

🟠HEAD
Метод HEAD аналогичен GET, но без тела ответа. Используется для получения метаданных о ресурсе, таких как заголовки, без загрузки самого ресурса.

🟠OPTIONS
Метод OPTIONS используется для запроса информации о поддерживаемых методах на сервере или на конкретном ресурсе. Это может быть полезно для определения доступных операций перед отправкой основного запроса.

🟠CONNECT
Метод CONNECT используется для установления туннеля к серверу через прокси. Обычно используется для HTTPS через прокси.

🟠TRACE
Метод TRACE выполняет тестовый запрос по маршруту до ресурса. Он возвращает запрос, полученный сервером, что может помочь в диагностике сетевых проблем или выявлении изменений в маршруте запроса.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
4
🏗️ Модуль child_process — запуск внешних программ и скриптов

Иногда возможностей Node.js не хватает, и нужно вызвать системную команду, запустить Python-скрипт или скомпилировать C++ код. Модуль child_process позволяет Node.js порождать дочерние процессы и общаться с ними.

child_process — работа с системными командами

exec()
spawn()
fork()
execFile()

exec() — запускает команду в оболочке (shell) и буферизирует весь вывод. Идеально для коротких команд, результат которых помещается в память.

const { exec } = require('child_process');

exec('ls -lh', (err, stdout, stderr) => {
if (err) return console.error(err);
console.log(`Файлы:\n${stdout}`);
});




spawn() — запускает процесс и работает с ним через потоки (streams). Это лучший выбор для тяжелых задач или команд с огромным выводом, так как данные передаются частями.

const { spawn } = require('child_process');
const child = spawn('find', ['/']);

child.stdout.on('data', (data) => {
console.log(`Чанк данных: ${data.length}`);
});


fork() — специальный метод для запуска других Node.js модулей. Он создает выделенный канал связи (IPC) между родителем и ребенком, позволяя обмениваться объектами через send().

// В родительском коде
const n = fork('worker.js');
n.on('message', (m) => console.log('Получено:', m));
n.send({ hello: 'world' });


Безопасность — никогда не передавайте данные от пользователя напрямую в exec(), иначе злоумышленник может выполнить произвольный код на сервере (Command Injection). Используйте spawn() с массивом аргументов — это безопаснее.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🚀 Модуль worker_threads — настоящий параллелизм в Node.js

Если cluster копирует весь процесс, то worker_threads позволяет запускать тяжелые вычисления в отдельных потоках внутри одного и того же процесса. Это идеальное решение для задач, которые нагружают процессор (CPU-intensive), таких как обработка изображений или сложные математические расчеты.

worker_threads — многопоточность без копирования процессов

Worker
parentPort
isMainThread
workerData

isMainThread — флаг, который помогает понять, выполняется ли код в основном потоке или внутри воркера.

const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');

if (isMainThread) {
const worker = new Worker(__filename, { workerData: 'начать расчет' });
worker.on('message', (result) => console.log('Результат:', result));
} else {
const result = `Воркер получил: ${workerData}`;
parentPort.postMessage(result);
}




workerData — позволяет передавать данные из основного потока в воркер при его создании. Это могут быть любые клонируемые объекты.

parentPort — специальный канал связи, через который воркер может отправлять сообщения обратно в основной поток с помощью postMessage().

SharedArrayBuffer — в отличие от cluster, воркеры могут разделять одну и ту же область памяти. Это позволяет огромным массивам данных быть доступными для всех потоков одновременно без затрат на копирование.

Зачем это нужно? — Обычный код Node.js блокирует Event Loop при тяжелых циклах. Воркеры позволяют перенести эти циклы «в сторону», чтобы сервер продолжал отвечать на запросы других пользователей.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
📡 Модуль net — фундамент сетевого взаимодействия

Если http — это высокоуровневый стандарт для веба, то модуль net — это «низкий уровень». Он позволяет работать напрямую с TCP-сокетами, создавая серверы и клиенты, которые общаются голыми данными без лишних заголовков.

net — создание TCP-серверов и сокетов

net.createServer()
net.connect()
socket.write()
socket.pipe()

net.createServer() — создает TCP-сервер. В отличие от HTTP, здесь вы сами решаете, какой протокол использовать для общения — будь то чат, передача файлов или свой проприетарный формат.

const net = require('net');

const server = net.createServer((socket) => {
socket.write('Привет от TCP сервера!\n');
socket.on('data', (data) => {
console.log('Клиент прислал:', data.toString());
});
});

server.listen(8080);




net.connect() — создает клиентское соединение с сервером по IP и порту. Это база для написания своих баз данных, прокси-серверов или систем мониторинга.

const client = net.connect({ port: 8080 }, () => {
console.log('Подключено к серверу!');
client.write('Привет, сервер!');
});


socket.pipe() — сокеты в Node.js являются дуплексными стримами. Это значит, что вы можете «пробросить» данные из одного соединения в другое одной командой. Так пишутся простейшие прокси-серверы.

IPC (Inter-Process Communication) — модуль net умеет работать не только с сетью, но и с локальными именованными каналами (Unix Domain Sockets). Это самый быстрый способ заставить два процесса на одном сервере обмениваться данными

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
🛡️ Модуль tls — защищенные сетевые соединения

Если модуль net работает с «голым» TCP, то tls (Transport Layer Security) добавляет поверх него слой шифрования. Это фундамент для создания защищенных серверов, таких как HTTPS, и безопасной передачи данных, которую невозможно перехватить.

tls — шифрование сетевого трафика

tls.createServer()
tls.connect()
pfx / key / cert
ALPN

tls.createServer() — создает сервер, который требует SSL/TLS сертификаты для работы. Без них браузер или клиент не смогут установить безопасное соединение.

const tls = require('tls');
const fs = require('fs');

const options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
};

tls.createServer(options, (socket) => {
socket.write('Вы подключены по защищенному каналу!\n');
socket.pipe(socket);
}).listen(8000);




Сертификаты (Key & Cert) — для работы tls нужны закрытый ключ (key) и сертификат (cert). В разработке часто используют самоподписанные сертификаты, но в продакшене — только от доверенных центров (CA).

tls.connect() — позволяет создать клиент, который безопасно подключается к TLS-серверу. Он автоматически проверяет валидность сертификата сервера, защищая от атак типа «человек посередине» (MITM).

ALPN (Application-Layer Protocol Negotiation) — расширение TLS, которое позволяет клиенту и серверу договориться, какой протокол использовать (например, HTTP/2 или HTTP/1.1) еще в процессе установки защищенного соединения.

Безопасность — модуль tls по умолчанию использует современные протоколы (TLS 1.2 и 1.3) и отключает старые, уязвимые версии (вроде SSLv3), обеспечивая высокий уровень защиты «из коробки».



Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🛡️ Модуль os — информация об операционной системе

Модуль os предоставляет методы для взаимодействия с операционной системой, на которой запущен Node.js. Это позволяет адаптировать работу приложения под конкретное железо: узнавать количество ядер, объем свободной оперативной памяти или домашнюю директорию пользователя.

os — системные данные и ресурсы

os.cpus()
os.freemem() / os.totalmem()
os.networkInterfaces()
os.homedir()
os.platform()

os.cpus() — возвращает массив объектов с данными о каждом ядре процессора (модель, скорость, время работы). Это ключевой метод для автоматического масштабирования через модуль cluster.

const os = require('os');
console.log(`Ядер процессора: ${os.cpus().length}`);




os.freemem() / os.totalmem() — показывают объем свободной и общей оперативной памяти в байтах. Помогает приложению понять, стоит ли сейчас запускать тяжелую задачу или памяти уже критически мало.

const freeGB = (os.freemem() / 1024 / 1024 / 1024).toFixed(2);
console.log(`Свободно памяти: ${freeGB} GB`);


os.networkInterfaces() — выдает детальную информацию о сетевых интерфейсах (IP-адреса, MAC-адреса). Нужно, если вашему серверу необходимо знать свой локальный или внешний IP.

os.platform() / os.type() — возвращают название платформы (win32, linux, darwin). Позволяет писать условия для специфических системных команд.

if (os.platform() === 'win32') {
console.log('Запущено на Windows');
}


os.homedir() — возвращает путь к домашней папке текущего пользователя. Это гораздо надежнее, чем пытаться угадать путь вручную.


Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🧪 Модуль assert — простейшее тестирование и валидация

Модуль assert предназначен для проверки условий в коде. Если условие не выполняется, программа выбрасывает ошибку. Это встроенный инструмент для написания тестов и защиты от некорректных данных на этапе разработки.

assert — утверждения и проверки

assert.strictEqual()
assert.deepStrictEqual()
assert.throws()
assert.ok()

assert.ok() — проверяет, является ли значение истинным (truthy). Если передать false, 0 или null, программа выдаст ошибку.

const assert = require('assert');

assert.ok(5 > 2); // Всё ок
// assert.ok(1 === 2, 'Единица не равна двойке!'); // Выбросит AssertionError




assert.strictEqual() — проверяет равенство значений и их типов (как оператор ===). Идеально для проверки того, что функция вернула именно то, что вы ожидали.

assert.deepStrictEqual() — незаменим для сравнения объектов и массивов. Обычное === сравнивает ссылки, а этот метод заглядывает внутрь и сравнивает каждое свойство.

const obj1 = { a: { b: 1 } };
const obj2 = { a: { b: 1 } };

// assert.strictEqual(obj1, obj2); // Ошибка (разные ссылки)
assert.deepStrictEqual(obj1, obj2); // Всё ок (содержимое одинаковое)


assert.throws() — проверяет, что функция действительно выдает ошибку при определенных условиях. Это важно для тестирования обработки исключений.

assert.throws(
() => { throw new Error('Упс!'); },
/Упс/
);


Строгий режим — рекомендуется всегда использовать assert.strict, так как он применяет более строгие правила сравнения, предотвращая случайные ошибки с приведением типов.

Backend Ready | #урок
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Вот одна из самых базовых вещей про то, как работает память в операционных системах, но со временем многие это просто забывают. Небольшое напоминание: когда вы вызываете malloc(), вы на самом деле не получаете память, вы получаете обещание.

Когда вы делаете malloc на 1 ГБ, ОС говорит: «Окей, вот тебе 1 ГБ», но реально пока не отдает ни одного байта. На этом этапе выделяется виртуальная память, а фактическое потребление RAM, то есть RSS (Resident Set Size), остается прежним.

Это и есть lazy allocation. ОС назначает реальные страницы только тогда, когда вы начинаете в них писать. Вы можете вызвать malloc() хоть на терабайты на ноутбуке с 16 ГБ RAM, и вызов пройдет успешно. Падение, тот самый segmentation fault, случится позже, когда вы попытаетесь эту память использовать, а система уже не сможет ее реально предоставить.

- malloc(1GB) -> виртуальная память +1 ГБ, RSS +0 МБ
- memset(ptr, 0, 1GB) -> RSS +1 ГБ

Почему это важно? Потому что именно RSS реально конкурирует за ресурсы. Именно на него смотрит OOM killer, и именно он в итоге тормозит систему.

У вас может быть процесс, который в профайлере показывает 10 ГБ выделенной памяти, а реально потребляет только 2 ГБ RAM. Разница возникает потому, что большая часть этих областей, выделенных через malloc, была зарезервирована, но к ней так и не было доступа.

Кстати, именно поэтому утечки памяти могут долго оставаться незаметными. Если вы сделали malloc(), потеряли указатель и ни разу в эту память не записали, то вы утекли по виртуальному адресному пространству, но не по физической памяти.

Самый простой способ посмотреть RSS процесса, это запустить ps aux. В выводе вы увидите VSZ (virtual) и RSS (resident) в КБ. Это можно получить и программно :)

Так что всегда следите именно за RSS, а не только за объемом памяти, выделенной через malloc, если хотите понимать, сколько памяти процесс реально потребляет.
4
🛠️ Модуль util — вспомогательные инструменты для разработчика

Модуль util содержит набор полезных функций, которые упрощают отладку и расширяют возможности стандартного JavaScript. Он помогает форматировать строки, работать с промисами и проверять типы данных без лишнего кода.

util — утилиты и полифиллы

util.promisify()
util.format()
util.inspect()
util.callbackify()

util.promisify() — один из самых важных методов. Он превращает любую функцию, работающую на колбэках, в функцию, которая возвращает Promise. Это позволяет использовать async/await со старыми библиотеками.

const util = require('util');
const fs = require('fs');

const readFile = util.promisify(fs.readFile);
const data = await readFile('config.json', 'utf8');



util.inspect() — продвинутая замена console.log для объектов. Он умеет красиво подсвечивать синтаксис, ограничивать глубину вложенности и показывать скрытые свойства (неперечисляемые).

const obj = { a: 1, b: { c: 2 } };
console.log(util.inspect(obj, { colors: true, depth: 0 }));



util.format() — позволяет создавать строки с использованием спецификаторов (как в языке C). Удобно для создания кастомных логов с динамическими данными.

const msg = util.format('Пользователь %s залогинился в %d:00', 'Admin', 12);
// Результат: Пользователь Admin залогинился в 12:00



util.deprecate() — помечает функцию как устаревшую. При её вызове пользователь увидит в консоли предупреждение, но программа продолжит работу. Идеально для поддержки старых версий вашего API.

Проверки типов — раньше в util было много методов вроде isArray, но теперь они переехали в глобальные объекты (Array.isArray). Тем не менее, util.types всё еще полезен для проверки специфических объектов движка (например, isRegExp или isDate).

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
1
🧪 Модуль zlib — сжатие данных «на лету»

Модуль zlib предоставляет возможности для архивации данных. Это критически важно для веб-серверов: сжатие HTTP-ответов с помощью Gzip или Brotli позволяет уменьшить размер передаваемого трафика в несколько раз, ускоряя загрузку сайта для пользователей.

zlib — алгоритмы сжатия Gzip, Deflate и Brotli

createGzip() / createGunzip()
createBrotliCompress()
gzip() / gunzip()
pipeline()

Сжатие файловzlib лучше всего работает в связке со стримами. Вы можете читать файл, «прогонять» его через поток сжатия и сразу записывать результат в архив, не загружая весь файл в память.

const zlib = require('zlib');
const fs = require('fs');
const { pipeline } = require('stream');

const gzip = zlib.createGzip();
const source = fs.createReadStream('input.txt');
const destination = fs.createWriteStream('input.txt.gz');

pipeline(source, gzip, destination, (err) => {
if (err) console.error('Ошибка сжатия:', err);
});



Brotli против Gzip — Node.js поддерживает современный алгоритм Brotli, который сжимает текстовые данные (HTML, JS, CSS) на 15-20% эффективнее, чем старый добрый Gzip. В модуле он доступен через createBrotliCompress.

Сжатие «в памяти» — если данных немного, можно использовать методы с колбэками или промисами для быстрого сжатия буфера без создания стримов.

const input = 'Много повторяющегося текста текста текста';
zlib.gzip(input, (err, buffer) => {
console.log('Сжатый размер:', buffer.length);
});



HTTP-оптимизация — если вы пишете свой сервер на модуле http, вы можете проверять заголовок Accept-Encoding и автоматически сжимать ответ, если браузер клиента это поддерживает.

Уровни сжатия — вы можете настраивать баланс между скоростью и качеством сжатия (параметр level). Чем выше уровень, тем меньше файл, но тем больше нагрузки на процессор.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Модуль readline — интерактивный ввод в консоли
Если тебе нужно создать CLI-интерфейс, который задает вопросы пользователю и обрабатывает ответы, модуль readline — самый простой встроенный способ это сделать. Он позволяет читать данные из стандартного потока ввода (process.stdin) построчно.

readline — интерфейс для командной строки

createInterface()
question()
on('line')
close()

Интерфейс ввода-вывода — для работы нужно создать экземпляр интерфейса, связав его с вводом (stdin) и выводом (stdout) консоли.

const readline = require('readline');

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});



question() — метод, который выводит вопрос в консоль и ждет, пока пользователь нажмет Enter. Ответ передается в колбэк.

rl.question('Как тебя зовут? ', (answer) => {
console.log(`Привет, ${answer}!`);
rl.close();
});



Чтение потока — если нужно обрабатывать каждую введенную строку (например, для создания чат-бота или кастомной оболочки), используется событие line. Оно срабатывает каждый раз, когда пользователь нажимает Enter.

rl.on('line', (input) => {
console.log(`Ты ввел: ${input}`);
});



Promises API — в новых версиях Node.js можно использовать readline/promises, чтобы не тонуть в колбэках и работать через await.

const readline = require('readline/promises');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});

const age = await rl.question('Сколько тебе лет? ');
console.log(`Твой возраст: ${age}`);
rl.close();



Завершение работы — важно всегда вызывать rl.close(), иначе процесс Node.js будет продолжать висеть в памяти, ожидая нового ввода.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
🔗 Модуль path — работа с путями к файлам и папкам

Разные операционные системы используют разные разделители путей: Windows предпочитает обратный слэш (\), а Linux и macOS — прямой (/). Модуль path позволяет писать кроссплатформенный код, который будет корректно работать на любой системе, автоматически подстраиваясь под её правила.

path — манипуляция путями без ошибок

path.join()
path.resolve()
path.extname()
path.parse()

path.join() — объединяет сегменты пути в одну строку, используя специфичный для системы разделитель. Это гораздо надежнее, чем складывать строки через +.

const path = require('path');
const fullPath = path.join('users', 'bairas', 'projects', 'app.js');
// Windows: users\bairas\projects\app.js
// Linux: users/bairas/projects/app.js



path.resolve() — превращает последовательность путей в абсолютный путь. Он работает как команда cd в терминале: берет текущую рабочую директорию и «наслаивает» на неё переданные сегменты.

path.extname() — моментально возвращает расширение файла. Полезно, когда нужно отфильтровать только .jpg картинки или .js скрипты в папке.

console.log(path.extname('index.html')); // '.html'



path.parse() — разбирает строку пути на составные части: корень, директорию, базовое имя, расширение и имя файла без расширения. Возвращает удобный объект.

const info = path.parse('/home/user/dir/file.txt');
/*
{
root: '/',
dir: '/home/user/dir',
base: 'file.txt',
ext: '.txt',
name: 'file'
}
*/



dirname и filename — хотя это глобальные переменные, их почти всегда используют вместе с модулем path, чтобы вычислить путь к файлам относительно текущего скрипта, а не от места запуска терминала.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🔐 Модуль crypto — криптография и безопасность

Модуль crypto предоставляет набор криптографических функций, которые позволяют защитить данные в вашем приложении. Это не просто инструмент для «закрытия» данных, а мощный движок для создания хешей, генерации ключей, шифрования и работы с цифровыми подписями.

crypto — шифрование и хеширование

createHash()
createHmac()
createCipheriv() / createDecipheriv()
randomBytes()

Хеширование (createHash) — превращает строку в уникальный отпечаток фиксированной длины. Это необратимый процесс, который чаще всего используется для проверки целостности файлов или сравнения паролей (хотя для паролей лучше подходят специализированные алгоритмы вроде Argon2).

const crypto = require('crypto');
const hash = crypto.createHash('sha256').update('секретный_пароль').digest('hex');
console.log(hash);



HMAC (createHmac) — это хеш-код, который создается с использованием секретного ключа. Он гарантирует не только то, что данные не изменились, но и то, что они были отправлены именно тем, у кого есть этот ключ. Часто используется в API для подписи запросов.

Симметричное шифрование (createCipheriv) — позволяет зашифровать данные так, чтобы их можно было расшифровать обратно. Для этого используется алгоритм (например, AES-256), ключ и вектор инициализации (IV).

const algorithm = 'aes-256-cbc';
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);

const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update('секретные данные', 'utf8', 'hex');
encrypted += cipher.final('hex');



randomBytes() — генерирует криптографически стойкие случайные данные. В отличие от стандартного Math.random(), результат этого метода невозможно предугадать, что делает его идеальным для создания токенов, солей для паролей и ключей сессий.

Цифровые подписи — методы sign и verify позволяют подписывать данные закрытым ключом и проверять их открытым. Это основа безопасности в распределенных системах и блокчейне.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
1
📡 Модуль http — создание веб-серверов без библиотек

Модуль http — это сердце сетевых возможностей Node.js. Именно на нем построены такие гиганты, как Express или Fastify. Он позволяет создать полноценный веб-сервер, который умеет принимать запросы, парсить заголовки и отправлять ответы пользователям.

http — база веб-коммуникаций

createServer()
request()
IncomingMessage
ServerResponse

createServer() — основной метод для запуска сервера. В колбэк приходят два объекта: req (запрос от пользователя) и res (твой ответ ему).

const http = require('http');

const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Привет! Ты на сервере Node.js');
});

server.listen(3000);



IncomingMessage (req) — объект, из которого можно достать всё о клиенте: URL, метод (GET/POST), заголовки и тело запроса. Поскольку это поток (Stream), данные из тела запроса нужно собирать по частям.

ServerResponse (res) — через этот объект ты управляешь тем, что увидит пользователь. Ты можешь устанавливать статус-коды (200, 404, 500) и отправлять данные в любом формате: от обычного текста до JSON или HTML.

http.request() — позволяет Node.js самому выступать в роли клиента. С его помощью можно делать запросы к сторонним API или микросервисам.

const options = {
hostname: 'google.com',
port: 80,
path: '/',
method: 'GET'
};

const req = http.request(options, (res) => {
console.log(`Статус: ${res.statusCode}`);
});
req.end();



Производительность — стандартный модуль http очень быстрый, так как не содержит лишних «надстроек». Это отличный выбор, когда нужно написать максимально легкий микросервис или прокси-сервер.

Backend Ready | #Уроки
Please open Telegram to view this post
VIEW IN TELEGRAM
3