URL.revokeObjectURL: примеры (JAVASCRIPT)

Освобождение blob URL с помощью revokeObjectURL
Раздел: URL, Освобождение URL
URL.revokeObjectURL(objectURL: String): undefined

Основы метода URL.revokeObjectURL

Метод URL.revokeObjectURL() освобождает существующий URL объекта, созданный ранее с помощью URL.createObjectURL(). Он позволяет явно указать браузеру, что ссылка на ресурс более не требуется, что дает возможность сборщику мусора освободить связанную память.

Использование метода целесообразно после завершения работы с объектами Blob или File, например, после загрузки файла пользователем, предварительного просмотра изображения или завершения передачи данных через URL. Это помогает предотвратить утечки памяти в веб-приложениях.

Аргументы функции:

  • url (обязательный) - строка DOMString, представляющая URL объекта, который нужно отозвать. Это значение должно быть получено из успешного вызова URL.createObjectURL(). Передача некорректного или уже отозванного URL не вызывает исключения.
Возвращаемое значение: undefined. Метод не возвращает значимого результата.

Простые примеры использования

Отзыв URL после предварительного просмотра изображения:

const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.onchange = (e) => {
  const file = e.target.files[0];
  const objectURL = URL.createObjectURL(file);
  const img = document.createElement('img');
  img.src = objectURL;
  document.body.appendChild(img);
  // Отзыв после загрузки изображения
  img.onload = () => URL.revokeObjectURL(objectURL);
};
document.body.appendChild(input);
// После загрузки изображения URL будет отозван
// и память освобождена

Отзыв нескольких созданных URL:

const blobs = [
  new Blob(['content1'], { type: 'text/plain' }),
  new Blob(['content2'], { type: 'text/plain' })
];
const urls = blobs.map(blob => URL.createObjectURL(blob));
console.log(urls); // ['blob:http://example.com/uuid1', ...]

// Освобождение всех URL
urls.forEach(url => URL.revokeObjectURL(url));
console.log(urls[0]); // URL остается строкой, но становится недействительным
['blob:http://example.com/uuid1', 'blob:http://example.com/uuid2']
'blob:http://example.com/uuid1'

Альтернативы в JavaScript

URL.createObjectURL() и URL.revokeObjectURL() работают в паре. Первая создает временные URL, вторая их освобождает.

FileReader.readAsDataURL() предоставляет альтернативный способ доступа к данным файлов через схему data:. Этот метод создает строку в формате base64, которую не требуется явно освобождать, но она может занимать больше памяти при работе с большими файлами. Выбор между этими подходами зависит от сценария: createObjectURL эффективнее для больших бинарных данных, а readAsDataURL удобнее для небольших файлов, которые нужно передать напрямую в HTML или CSS.

Распространенные ошибки

Преждевременный отзыв URL до завершения использования ресурса:

const blob = new Blob(['content'], { type: 'text/html' });
const url = URL.createObjectURL(blob);
const iframe = document.createElement('iframe');
iframe.src = url;
URL.revokeObjectURL(url); // Слишком рано!
document.body.appendChild(iframe); // iframe может не загрузиться
// iframe получает недействительный URL
// и может отображать ошибку

Попытка повторного отзыва одного URL:

const url = URL.createObjectURL(new Blob(['test']));
URL.revokeObjectURL(url);
URL.revokeObjectURL(url); // Второй вызов игнорируется
console.log('Без ошибки');
'Без ошибки'

Использование строки, не являющейся blob URL:

URL.revokeObjectURL('https://example.com'); // Не blob URL
console.log('Код выполнен');
'Код выполнен'

Изменения в спецификации

Метод URL.revokeObjectURL() не претерпел значительных изменений в последних версиях стандартов. Однако, с появлением Streams API и усовершенствований в работе с памятью, рекомендации по использованию стали более строгими. В современных браузерах автоматическое освобождение памяти для неотозванных blob URL может происходить при выгрузке документа, но явный вызов метода остается лучшей практикой для управления памятью.

Расширенные примеры применения

Использование с видео и автоматический отзыв после окончания воспроизведения:

Пример javascript
const video = document.createElement('video');
const blob = new Blob([videoData], { type: 'video/mp4' });
const videoUrl = URL.createObjectURL(blob);
video.src = videoUrl;
video.addEventListener('ended', () => {
  URL.revokeObjectURL(videoUrl);
  console.log('URL видео отозван');
}, { once: true });

Интеграция с React и useEffect для управления жизненным циклом:

Пример javascript
import { useEffect, useRef } from 'react';

function PdfViewer({ pdfBlob }) {
  const objectUrlRef = useRef(null);
  
  useEffect(() => {
    if (pdfBlob) {
      objectUrlRef.current = URL.createObjectURL(pdfBlob);
    }
    return () => {
      if (objectUrlRef.current) {
        URL.revokeObjectURL(objectUrlRef.current);
      }
    };
  }, [pdfBlob]);
  
  return pdfBlob ? (
    <iframe src={objectUrlRef.current} />
  ) : null;
}

Пакетное создание и отзыв URL для множества файлов с обработкой ошибок:

Пример javascript
async function processFiles(files) {
  const urls = [];
  try {
    for (const file of files) {
      if (!file.type.startsWith('image/')) continue;
      const url = URL.createObjectURL(file);
      urls.push(url);
      await new Promise(resolve => {
        const img = new Image();
        img.onload = resolve;
        img.src = url;
      });
      // Обработка изображения
    }
  } finally {
    urls.forEach(url => URL.revokeObjectURL(url));
  }
}

Создание и отзыв URL для медиапотоков с устройства:

Пример javascript
navigator.mediaDevices.getUserMedia({ video: true })
  .then(stream => {
    const mediaRecorder = new MediaRecorder(stream);
    const chunks = [];
    mediaRecorder.ondataavailable = e => chunks.push(e.data);
    mediaRecorder.onstop = () => {
      const blob = new Blob(chunks, { type: 'video/webm' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'record.webm';
      a.click();
      setTimeout(() => URL.revokeObjectURL(url), 100);
    };
    mediaRecorder.start();
  });

Решения в других языках программирования

В Python для работы с временными файлами используется модуль tempfile:

import tempfile
import os

# Создание временного файла
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.txt')
temp_file.write(b'temporary content')
temp_file.close()

# Использование файла
print(temp_file.name)

# Явное удаление (аналог revoke)
os.unlink(temp_file.name)
'/tmp/tmp1234.txt'

В PHP для очистки ресурсов часто используется unlink для файлов и fclose для дескрипторов:

<?php
$tempFile = tmpfile(); // Создает временный файл
fwrite($tempFile, 'content');
// ... использование
fclose($tempFile); // Файл автоматически удаляется
?>

В C для работы с временными файлами можно использовать функции стандартной библиотеки:

#include <stdio.h>
#include <unistd.h>

int main() {
  char filename[] = '/tmp/tempfileXXXXXX';
  int fd = mkstemp(filename); // Создание временного файла
  write(fd, 'data', 4);
  close(fd); // Закрытие дескриптора
  unlink(filename); // Удаление файла (аналог revoke)
  return 0;
}

JS URL.revokeObjectURL function comments

En
URL.revokeObjectURL Releases an existing object URL created by createObjectURL()