Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про JavaScript: fetch, streams API, memory overflow, large file download, ReadableStream

Почему при скачивании больших файлов через fetch возникает проблема переполнения памяти?

Вопрос проверяет понимание работы потоков данных (streams) в браузере при обработке больших ответов от сервера и знание способов избежать переполнения памяти.

Короткий ответ

При обычном вызове методов fetch().then(res => res.json()) или res.blob() браузер загружает весь ответ в память перед тем, как передать его в ваш код. Если файл весит гигабайты, он целиком помещается в оперативную память, что может исчерпать доступные ресурсы и привести к падению вкладки или приложения. Чтобы избежать этого, нужно работать с ответом как с потоком (stream), обрабатывая данные по частям по мере их поступления с сервера, не накапливая их все сразу.

Длинный ответ

Когда вы используете fetch для получения данных, браузер по умолчанию буферизует весь ответ тела (body) в памяти. Это удобно для небольших JSON-ответов или изображений, но становится проблемой для больших файлов, таких как видео, архивы или дампы баз данных.

Почему происходит переполнение памяти?

Методы response.json(), response.text() или response.blob() читают всё тело ответа и преобразуют его в соответствующий формат, полностью сохраняя результат в памяти JavaScript. Если файл размером 2 ГБ, то перед обработкой в вашем коде браузер должен выделить как минимум 2 ГБ оперативной памяти под этот буфер. Это может превысить лимиты памяти, доступные для вкладки браузера, и привести к ошибке "out of memory" или просто к зависанию.

Решение: Использование Streams API

Современный API fetch возвращает объект Response, у которого свойство body является ReadableStream. Этот поток позволяет читать данные чанками (кусками) по мере их поступления с сервера. Вы можете обрабатывать каждый чанк и сразу освобождать память, не дожидаясь загрузки всего файла.

Практический пример

Вот как можно скачать большой файл и сохранить его на диск пользователя с помощью потоков, избегая переполнения памяти:

async function downloadLargeFile(url, filename) {
  // Запрашиваем ресурс
  const response = await fetch(url);
  // Получаем поток из тела ответа
  const readableStream = response.body;
  
  // Создаём поток для записи в файл через File System Access API
  // (в реальном коде нужна проверка поддержки браузером)
  const fileStream = await createWritableStream(filename);
  
  // Потоково копируем данные из ответа в файл
  await readableStream.pipeTo(fileStream);
  
  console.log('Файл сохранён!');
}

// Упрощённая функция для демонстрации (в реальности используйте showSaveFilePicker)
async function createWritableStream(filename) {
  // Для примера: создаём объект Blob и ссылку для скачивания
  // Это не потоковое сохранение на диск, а демонстрация обработки чанков.
  const chunks = [];
  const writer = {
    write(chunk) {
      // Обрабатываем каждый чанк данных
      chunks.push(chunk);
      // Здесь можно, например, отправлять чанк в WebSocket
      // или вычислять хэш-сумму на лету
      console.log(`Получено ${chunk.byteLength} байт`);
    },
    close() {
      // В конце собираем файл (для примера, в реальности так делать не нужно)
      const blob = new Blob(chunks);
      const link = document.createElement('a');
      link.href = URL.createObjectURL(blob);
      link.download = filename;
      link.click();
    }
  };
  return writer;
}

Где это применяется?

  • Стриминг видео или аудио в веб-приложениях.
  • Загрузка и предварительный просмотр больших логов или CSV-файлов.
  • Постепенная обработка данных с сервера (например, прогрессивная загрузка JSON).
  • Клиентская обработка файлов, которые не помещаются в память целиком (шифрование, хэширование).

Вывод: Используйте Streams API через response.body при работе с потенциально большими ответами от сервера, чтобы обрабатывать данные по частям и избегать переполнения памяти. Это критически важно для создания отзывчивых веб-приложений, работающих с большими объёмами данных.

Уровень

  • Рейтинг:

    3

  • Сложность:

    5

Навыки

  • JavaScript

    JavaScript

  • HTML

    HTML

Ключевые слова

#fetch

#streams API

#memory overflow

#large file download

#ReadableStream

Подпишись на React Developer в телеграм