← Назад к вопросам
Когда допустимо использовать синхронные методы для работы с файловой системой?
2.0 Middle🔥 141 комментариев
#Node.js и JavaScript
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда допустимо использовать синхронные методы для работы с файловой системой?
Синхронные методы файловой системы (fs.readFileSync(), fs.writeFileSync() и т.д.) допустимо использовать только в ограниченных случаях, так как они блокируют выполнение всего приложения.
Когда МОЖНО использовать синхронные методы
// ✓ 1. Инициализация приложения (startup)
const config = require('fs').readFileSync('./config.json', 'utf-8');
const settings = JSON.parse(config);
// ✓ 2. Загрузка переменных окружения
const env = require('fs').readFileSync('.env', 'utf-8');
require('dotenv').parse(env);
// ✓ 3. Чтение статических данных при запуске
const DATA = JSON.parse(fs.readFileSync('./data.json'));
// ✓ 4. Проверка наличия файла в начале
if (!fs.existsSync('./required-file.txt')) {
throw new Error('Required file not found');
}
// ✓ 5. CLI утилиты (не веб-сервер)
const input = fs.readFileSync('/dev/stdin', 'utf-8');
console.log(process.argv);
Когда НЕЛЬЗЯ использовать синхронные методы
// ✗ 1. В обработчиках HTTP запросов
app.get('/users/:id', (req, res) => {
// ПЛОХО! Блокирует весь сервер
const userData = fs.readFileSync('./users.json');
res.json(userData);
});
// ПРАВИЛЬНО — асинхронно
app.get('/users/:id', async (req, res) => {
const userData = await fs.promises.readFile('./users.json');
res.json(userData);
});
// ✗ 2. В цикле
users.forEach(user => {
// ПЛОХО! Блокирует на каждую итерацию
const file = fs.readFileSync(`./users/${user.id}.json`);
});
// ✗ 3. В middleware Express
app.use((req, res, next) => {
// ПЛОХО! Каждый запрос блокирует
const token = fs.readFileSync('./auth-key.txt');
next();
});
// ✗ 4. В event handlers
emitter.on('event', () => {
// ПЛОХО! Блокирует обработку других событий
fs.readFileSync('./log.txt');
});
Почему это плохо?
const fs = require('fs');
const express = require('express');
const app = express();
// ПЛОХОЙ ПРИМЕР
app.get('/data', (req, res) => {
console.log('1. Request начала');
const data = fs.readFileSync('./huge-file.json'); // Блокирует на 5 секунд
console.log('2. Data прочитана');
res.json(data);
});
setInterval(() => {
console.log('3. Interval fired');
}, 1000);
// Консоль:
// 1. Request начала
// [5 секунд молчания - весь сервер заморожен]
// 2. Data прочитана
// 3. Interval fired (только после разморозки)
Правильный подход
const fs = require('fs');
const express = require('express');
const app = express();
// ✓ ХОРОШИЙ ПРИМЕР
app.get('/data', async (req, res) => {
try {
console.log('1. Request начала');
const data = await fs.promises.readFile('./huge-file.json');
console.log('2. Data прочитана (без блокировки)');
res.json(JSON.parse(data));
} catch (error) {
res.status(500).json({ error: error.message });
}
});
setInterval(() => {
console.log('3. Interval fired');
}, 1000);
// Консоль:
// 1. Request начала
// 3. Interval fired (одновременно!)
// 2. Data прочитана
// 3. Interval fired
Синхронные методы при инициализации
// config.loader.js
const fs = require('fs');
class ConfigLoader {
static load() {
const configPath = process.env.CONFIG_PATH || './config.json';
const rawConfig = fs.readFileSync(configPath, 'utf-8');
return JSON.parse(rawConfig);
}
}
// app.js
const CONFIG = ConfigLoader.load(); // Один раз при старте
app.get('/api/settings', (req, res) => {
res.json(CONFIG);
});
Альтернативы синхронным методам
// ✗ Синхронный
const data = fs.readFileSync('./file.json');
// ✓ Callback
fs.readFile('./file.json', (err, data) => {
if (err) console.error(err);
});
// ✓ Promise
fs.promises.readFile('./file.json')
.then(data => console.log(data))
.catch(err => console.error(err));
// ✓ Async/await (лучший вариант)
async function load() {
try {
const data = await fs.promises.readFile('./file.json');
return data;
} catch (error) {
console.error(error);
}
}
Правило
Синхронные операции допусти только:
- При инициализации приложения
- В CLI утилитах и скриптах
- Для проверок перед стартом
Во всех остальных случаях используй асинхронные методы (fs.promises, async/await).