Пошук уроків, статей та іншого контенту
Синхронні й асинхронні операції з файлами, та коли безпечно використовувати кожен варіант.
Вбудований модуль fs надає доступ до файлової системи операційної системи — читання, запис, видалення файлів і папок. Більшість функцій існують у трьох варіантах: асинхронний з колбеком (readFile), синхронний (readFileSync) і Promise-based (fs/promises), розглянутий у попередньому уроці про асинхронні патерни.
import { readFileSync } from "node:fs";
import { readFile } from "node:fs/promises";
// Синхронний варіант — блокує Event Loop, поки файл не прочитається повністю
const content1 = readFileSync("./config.json", "utf-8");
// Асинхронний варіант — не блокує, інші операції можуть виконуватись паралельно
const content2 = await readFile("./config.json", "utf-8");Синхронні *Sync-функції блокують Event Loop на весь час операції — неприйнятно всередині обробника HTTP-запиту чи будь-якого коду, що виконується під час роботи сервера. Але вони цілком доречні на етапі запуску застосунку (одноразове читання конфігураційного файлу до того, як сервер почав приймати запити) чи в одноразових CLI-скриптах, де немає паралельних запитів, які можна заблокувати.
Шляхи до файлів різняться між операційними системами (роздільник / у Unix/macOS проти \ у Windows) — модуль path будує коректні шляхи незалежно від платформи, замість ручної конкатенації рядків:
import path from "node:path";
const configPath = path.join(__dirname, "config", "settings.json");
// На Unix: /home/user/app/config/settings.json
// На Windows: C:\app\config\settings.json — path.join сам обирає правильний роздільникУ ES Modules немає вбудованого __dirname (це специфіка CommonJS) — еквівалент отримують через path.dirname(fileURLToPath(import.meta.url)) з модулів node:path і node:url.
Типова помилка — файл не існує чи немає прав доступу; readFile у такому разі не «падає» мовчки, а повертає помилку через колбек/reject Promise, яку обов'язково потрібно обробити:
try {
const content = await readFile("./maybe-missing.json", "utf-8");
console.log(JSON.parse(content));
} catch (error) {
if (error.code === "ENOENT") {
console.log("Файл не знайдено — використовуємо конфігурацію за замовчуванням");
} else {
throw error; // невідома помилка — прокинути далі, а не проковтнути мовчки
}
}Використання readFileSync/writeFileSync у коді обробки HTTP-запиту — блокує сервер для всіх користувачів на час операції з диском.
Ручна конкатенація шляхів рядками (folder + "/" + file) замість path.join — ламається на Windows і при зайвих/відсутніх слешах.
Ігнорування коду помилки (error.code) і обробка всіх помилок файлової системи однаково — ENOENT (файл не знайдено) та EACCES (немає прав доступу) зазвичай потребують різної реакції застосунку.
Модуль fs надає синхронні, callback-based і Promise-based варіанти операцій із файлами — синхронні прийнятні лише поза обробкою запитів (старт застосунку, CLI-скрипти), у решті випадків потрібен асинхронний варіант, щоб не блокувати Event Loop. Модуль path будує кросплатформні шляхи замість ручної конкатенації рядків, а помилки файлової системи (з полем error.code) варто обробляти диференційовано, а не єдиним catch-усе блоком.