Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «readFileSync і його небезпека». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)`readFileSync` блокує весь event loop, поки триває читання файлу; у Node.js, який однопоточний, це означає, що жоден інший запит, таймер чи подія не обробляється, доки операція не завершиться. **Ключове:** в HTTP-сервері один виклик `readFileSync` на великий файл може "заморозити" відповідь усім клієнтам одночасно - замінюй на `await fs.promises.readFile()`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Що робить `readFileSync` ```javascript import fs from 'fs'; const data = fs.readFileSync('./data.txt', 'utf8'); console.log(data); ``` Метод `fs.readFileSync()` читає файл **синхронно** - тобто **блокує виконання програми**, поки операція повністю не завершиться. Node.js не перейде до наступного рядка коду, поки файл не буде прочитано. ## 2. Node.js - однопоточний Ось **головна причина**, чому синхронний I/O небезпечний: > Node.js працює на **одному потоці** (event loop). > Поки одна операція виконується синхронно, **весь потік блокується**. Це означає: - поки `readFileSync()` читає файл, - **жодні інші запити чи події** не обробляються: ні HTTP-запити, ні таймери, ні обробники подій. ## 3. Що реально відбувається при `readFileSync()` ### Асинхронна версія (`fs.readFile`) ```javascript Event Loop: → Відправив задачу "прочитати файл" у потік (thread pool) → Звільнився і може обслуговувати інші запити → Коли файл готовий - викликає callback ``` ### Синхронна версія (`fs.readFileSync`) ```javascript Event Loop: → Почав читати файл ⏸ Зупинився, чекає результату Більше нічого не робить → Продовжує лише після завершення операції ``` ## 4. Приклад проблеми ### server.js ```javascript import http from 'http'; import fs from 'fs'; const server = http.createServer((req, res) => { const data = fs.readFileSync('./bigfile.txt', 'utf8'); res.end(data); }); server.listen(3000); ``` Що станеться: - Перший запит читає файл 2 секунди - **усе інше зупиняється**; - Інші запити чекають; - Сервер "зависає" під навантаженням. ### Правильний варіант (асинхронно) ```javascript import http from 'http'; import { readFile } from 'fs/promises'; const server = http.createServer(async (req, res) => { const data = await readFile('./bigfile.txt', 'utf8'); res.end(data); }); server.listen(3000); ``` Тепер Node може: - одночасно читати файл, - і обслуговувати інші запити в черзі подій. ## 5. Приклад "небезпечної" ситуації ```javascript for (let i = 0; i < 1000; i++) { fs.readFileSync('./data.txt', 'utf8'); } ``` Тут кожна операція чекає попередню. Якщо файл великий - застосунок "зависне" на секунди чи хвилини. Тоді як асинхронна версія: ```javascript Promise.all( Array(1000).fill().map(() => readFile('./data.txt', 'utf8')) ); ``` читає файли **паралельно** (у thread pool). ## 6. Продуктивність у цифрах | Метод | Час (приблизно) | Потік блокується | |---|---|---| | `readFileSync()` | 100-300 мс на файл | Так | | `readFile()` | 100-300 мс (у фоні) | Ні | | `readFile` (через `fs/promises`) | 100-300 мс (у фоні) | Ні | На сервері з 1000 запитів на секунду кожен `readFileSync()` може "заморозити" потік і перетворити Node.js із високопродуктивного на однопотоковий bottleneck. ## 7. Коли `readFileSync()` допустимий **Можна використовувати:** - У скриптах, CLI-утилітах, міграціях (де немає конкуренції запитів); - Під час старту застосунку для завантаження конфігурації; - У тестах, де потрібно просто отримати дані; - Коли продуктивність не критична. **Не можна використовувати:** - В HTTP-серверах, Express/Fastify маршрутах; - В API чи обробниках подій; - В асинхронних чергах; - У продакшені з одночасними користувачами. ## 8. Аналогія Уяви, що Node.js - це офіціант: - `readFile()` - він передає замовлення на кухню й обслуговує інших клієнтів; - `readFileSync()` - він **стоїть на місці й чекає**, поки кухар приготує страву. ## 9. Як правильно замінити `readFileSync()` | Було (погано) | Стало (добре) | |---|---| | `fs.readFileSync()` | `await fs.promises.readFile()` | | `fs.writeFileSync()` | `await fs.promises.writeFile()` | | `fs.existsSync()` | `await fs.promises.access()` | ## Коротке резюме | Пункт | `readFileSync()` | `readFile()` / `fs.promises.readFile()` | |---|---|---| | Виконання | Синхронне | Асинхронне | | Блокує потік | Так | Ні | | Підходить для сервера | Ні | Так | | Простота | Так | Так (через `await`) | | Продуктивність | Погана під навантаженням | Відмінна | ## Одним реченням > `fs.readFileSync()` небезпечний у серверних застосунках, тому що **блокує весь event loop**, заважаючи Node.js обробляти інші запити, і перетворює асинхронний сервер на "завислий" однопоточний процес.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.