← Назад к вопросам

Какие знаешь синхронные операции?

1.3 Junior🔥 61 комментариев
#Node.js и JavaScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Синхронные операции в Node.js

Синхронные операции — это операции, которые блокируют Event Loop и выполняются последовательно. В production-среде их нужно минимизировать, но знать их важно.

1. Синхронные операции с файлами (fs module)

Файловые операции имеют как синхронную, так и асинхронную версию.

// ❌ СИНХРОННО (блокирует Event Loop)
const fs = require('fs');

const data = fs.readFileSync('file.txt', 'utf-8');
console.log(data);  // Ждём, пока файл загрузится

// Весь код ниже ждёт завершения readFile
const size = fs.statSync('file.txt').size;

// ✅ АСИНХРОННО (не блокирует)
fs.readFile('file.txt', 'utf-8', (err, data) => {
  console.log(data);
});

console.log('Это выполнится первым!');

Синхронные методы fs:

// Чтение
fs.readFileSync(path, encoding);
fs.readSync(fd, buffer, offset, length, position);

// Запись
fs.writeFileSync(path, data, encoding);
fs.appendFileSync(path, data);

// Информация
fs.statSync(path);
fs.lstatSync(path);

// Удаление
fs.unlinkSync(path);
fs.rmdirSync(path);

// Операции с директориями
fs.readdirSync(path);
mkdirSync(path);

2. Синхронные операции с криптографией

const crypto = require('crypto');

// ❌ СИНХРОННО
const hash = crypto.createHash('sha256');
hash.update('password');
const digest = hash.digest('hex');  // Быстро, но блокирует

// ✅ АСИНХРОННО (для тяжёлых операций)
const pbkdf2 = crypto.pbkdf2(
  'password',
  'salt',
  100000,
  32,
  'sha256',
  (err, key) => {
    console.log(key);  // Не блокирует Event Loop
  }
);

// Синхронная версия
const keySync = crypto.pbkdf2Sync('password', 'salt', 100000, 32, 'sha256');

3. JSON парсинг/сериализация

// Синхронная операция (обычно быстрая)
const data = JSON.parse(jsonString);
const json = JSON.stringify(obj);

// Опасна только на ОЧЕНЬ больших данных (>10MB)
const largeData = JSON.parse(hugeJsonString);  // Может заморозить

// Решение: парсить по кускам или использовать streaming
const { parser } = require('stream-json');
const fs = require('fs');

fs.createReadStream('huge.json')
  .pipe(parser())
  .on('data', (chunk) => {
    console.log(chunk);  // Не блокирует
  });

4. Синхронная обработка массивов

// ❌ СИНХРОННО (блокирует если данных много)
const users = Array(10000000).fill(null).map((_, i) => ({
  id: i,
  name: `User ${i}`,
  email: `user${i}@example.com`,
}));

// ✅ АСИНХРОННО (с помощью worker threads)
const { Worker } = require('worker_threads');

const worker = new Worker('./heavy-computation.js');
worker.on('message', (result) => {
  console.log(result);
});

5. Синхронные вычисления (CPU-bound)

// ❌ СИНХРОННО (блокирует, если долгие вычисления)
function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

const result = fibonacci(40);  // Будет ждать долго, блокируя Event Loop

// ✅ АСИНХРОННО (через Worker Threads)
const { Worker } = require('worker_threads');
const path = require('path');

function runFibonacci(n) {
  return new Promise((resolve, reject) => {
    const worker = new Worker(path.resolve(__filename), {
      workerData: n,
    });
    worker.on('message', resolve);
    worker.on('error', reject);
  });
}

await runFibonacci(40);  // Не блокирует Event Loop

6. Синхронные операции require/import

// СИНХРОННО (но нормально, потому что обычно на старте)
const express = require('express');
const fs = require('fs');
const config = require('./config.json');

// Проблема: require('динамический путь')
const moduleName = getUserModule();  // 'postgres' или 'mysql'
const db = require(`./db/${moduleName}`);  // Блокирует до загрузки

// Решение: асинхронно
const db = await import(`./db/${moduleName}.js`);

7. Синхронные операции с буферами

// СИНХРОННО
const buffer = Buffer.alloc(1000000);  // Создание буфера
const copied = buffer.copy(otherBuffer);  // Копирование
const str = buffer.toString('utf-8');  // Конвертирование

// На малых объёмах это нормально, но на больших может заморозить

8. Синхронная обработка в цикле

// ❌ СИНХРОННО (очень плохо)
for (let i = 0; i < 1000000; i++) {
  const hash = crypto.createHash('sha256');
  hash.update(`user${i}`);
  hash.digest('hex');  // 1 миллион итераций, блокирует
}

// ✅ АСИНХРОННО (батчевание)
const batchSize = 100;
for (let i = 0; i < 1000000; i += batchSize) {
  await Promise.all(
    Array.from({ length: batchSize }).map((_, j) => {
      const hash = crypto.createHash('sha256');
      hash.update(`user${i + j}`);
      return hash.digest('hex');
    })
  );
  // Даём Event Loop обработать другие события
  await new Promise(resolve => setImmediate(resolve));
}

9. Синхронные операции регулярных выражений

// СИНХРОННО
const regex = /([a-z]+)\d+/g;
const matches = largeString.match(regex);  // На больших строках может зависнуть

// Проблема: ReDoS (Regular Expression Denial of Service)
const dangerous = /^(a|a)*$/;  // Экспоненциальная сложность
const test = dangerous.test('aaaaaaaaaaaaaaaaaaab');  // Может зависнуть

// Решение: использовать timeout
const runWithTimeout = (fn, timeout) => {
  return Promise.race([
    fn(),
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Timeout')), timeout)
    ),
  ]);
};

await runWithTimeout(
  () => Promise.resolve(dangerous.test(str)),
  1000
);

10. Синхронный доступ к памяти

// СИНХРОННО (обычно быстро)
const obj = {};
obj.key = 'value';
const val = obj.key;

// Проблема только если много операций на объекте
for (let i = 0; i < 10000000; i++) {
  obj[`key${i}`] = i;  // Может замедлить
}

// Решение: использовать Map для больших объёмов
const map = new Map();
for (let i = 0; i < 10000000; i++) {
  map.set(`key${i}`, i);  // Быстрее
}

Таблица синхронных операций

ОперацияПримерное времяБлокирует?Решение
JSON.parse (10MB)100-500msДаStreaming парсинг
fs.readFileSync (1MB)50-200msДаfs.readFile
crypto.pbkdf2Sync100-500msДаcrypto.pbkdf2 (async)
Regex на 1MB10-100msДаtimeout + validation
Buffer copy (100MB)50-200msДаstream.pipe
Object lookup< 1msНетOK для small objects
Array iteration (1M)5-20msДаWorker threads

Общее правило

// Если операция займёт > 10ms, рассмотри асинхронность

function isBig(operation) {
  const start = performance.now();
  operation();
  const duration = performance.now() - start;
  return duration > 10;  // Если > 10ms, это проблема
}

Best Practice

// ✅ Хорошо: минимум синхронных операций
app.get('/api/data', async (req, res) => {
  // Асинхронно
  const data = await db.query('SELECT ...');
  const processed = await processLargeData(data);
  res.json(processed);
});

// ❌ Плохо: много синхронных операций
app.get('/api/data', (req, res) => {
  // Синхронно (блокирует Event Loop)
  const data = fs.readFileSync('data.json');
  const parsed = JSON.parse(data);
  const result = heavyComputation(parsed);
  res.json(result);
});

Вывод: в Node.js синхронные операции необходимы, но их нужно тщательно использовать. Операции < 1ms можно оставлять синхронными, операции > 10ms должны быть асинхронными.

Какие знаешь синхронные операции? | PrepBro