Learn JavaScript

URL.revokeObjectURL() - освобождение временного blob URL в JavaScript

URL.revokeObjectURL() освобождает временный blob: URL, который был создан через URL.createObjectURL().

Когда браузер создаёт blob URL, он связывает строку адреса с данными в памяти: файлом, изображением, текстом или другим Blob. Пока такой URL не освобождён, браузер продолжает хранить эту связь.

Синтаксис

URL.revokeObjectURL(objectURL)

Где:

  • objectURL - строка с временным blob: URL

Метод ничего не возвращает.

const blob = new Blob(["Привет"], {
  type: "text/plain",
});

const url = URL.createObjectURL(blob);

URL.revokeObjectURL(url);

После вызова URL.revokeObjectURL(url) этот временный адрес больше не стоит использовать.

Зачем нужен revokeObjectURL()

Blob URL обычно создают для локального предпросмотра или скачивания файла.

const url = URL.createObjectURL(file);

image.src = url;

Если такие URL создавать много раз и не освобождать, страница может расходовать лишнюю память. Особенно это заметно при работе с большими изображениями, видео или частой сменой файлов.

URL.revokeObjectURL() сообщает браузеру: этот временный адрес больше не нужен, связанные с ним ресурсы можно освободить.

Пример: освобождение предыдущего предпросмотра

Частый сценарий - пользователь несколько раз выбирает разные изображения.

<input class="photo-input" type="file" accept="image/*">
<img class="photo-preview" alt="">
const input = document.querySelector(".photo-input");
const preview = document.querySelector(".photo-preview");

let currentUrl = null;

input.addEventListener("change", () => {
  const file = input.files[0];

  if (!file) {
    return;
  }

  if (currentUrl) {
    URL.revokeObjectURL(currentUrl);
  }

  currentUrl = URL.createObjectURL(file);
  preview.src = currentUrl;
});

Перед созданием нового URL мы освобождаем старый. Так на странице остаётся только актуальный предпросмотр.

Пример: освобождение после загрузки изображения

Если blob URL нужен только для того, чтобы один раз показать изображение, его можно освободить после загрузки.

const url = URL.createObjectURL(file);

preview.onload = () => {
  URL.revokeObjectURL(url);
};

preview.src = url;

Здесь важно, что revokeObjectURL() вызывается не сразу, а после события load.

Если освободить URL слишком рано, браузер может не успеть прочитать данные.

const url = URL.createObjectURL(file);

preview.src = url;
URL.revokeObjectURL(url);

Такой код может сработать нестабильно: адрес уже удалён, а изображение ещё не загрузилось.

Пример: скачивание файла

Для скачивания сгенерированного файла blob URL часто нужен только на один клик.

const content = "name,score\nAnna,100\nIvan,90";

const blob = new Blob([content], {
  type: "text/csv",
});

const url = URL.createObjectURL(blob);

const link = document.createElement("a");
link.href = url;
link.download = "scores.csv";
link.click();

URL.revokeObjectURL(url);

После click() временный URL обычно уже не нужен, поэтому его можно освободить.

Если вы добавляете ссылку на страницу и пользователь должен нажать её позже, освобождать URL сразу нельзя. Делайте это после клика или при удалении ссылки.

Что будет после revokeObjectURL()

После освобождения blob URL перестаёт быть надёжным адресом к данным.

const blob = new Blob(["Текст"], {
  type: "text/plain",
});

const url = URL.createObjectURL(blob);

URL.revokeObjectURL(url);

console.log(url); // строка всё ещё существует

Сама переменная url никуда не исчезает. Но связь между этой строкой и данными уже разорвана.

Если нужно снова получить рабочий blob URL, создайте новый:

const newUrl = URL.createObjectURL(blob);

revokeObjectURL() не удаляет исходный Blob или File

URL.revokeObjectURL() удаляет только временную ссылку.

Сам объект Blob или File от этого не становится пустым и не пропадает.

const blob = new Blob(["Привет"], {
  type: "text/plain",
});

const url = URL.createObjectURL(blob);

URL.revokeObjectURL(url);

console.log(blob.size); // 12

Если исходный Blob всё ещё нужен, его можно использовать дальше и создать для него новый временный URL.

Когда вызывать revokeObjectURL()

Хорошее правило простое: освобождайте blob URL тогда, когда элемент или пользователь уже точно не будет его использовать.

Подходящие моменты:

  • перед созданием нового URL вместо старого
  • после загрузки изображения, если URL больше не нужен
  • после клика по временной ссылке для скачивания
  • при закрытии модального окна с предпросмотром
  • при удалении элемента со страницы
  • при очистке состояния компонента

Если вы не уверены, нужен ли URL ещё, лучше хранить его в переменной и освободить позже в понятном месте.

Частые ошибки

Освобождать URL сразу после установки src

const url = URL.createObjectURL(file);

image.src = url;
URL.revokeObjectURL(url);

Браузер может не успеть загрузить данные. Для изображения безопаснее дождаться load.

const url = URL.createObjectURL(file);

image.onload = () => {
  URL.revokeObjectURL(url);
};

image.src = url;

Забывать освобождать старые URL при замене файла

input.addEventListener("change", () => {
  const file = input.files[0];
  image.src = URL.createObjectURL(file);
});

При каждой смене файла создаётся новый URL, а старые остаются висеть.

Лучше хранить текущий адрес и освобождать его перед заменой.

let currentUrl = null;

input.addEventListener("change", () => {
  const file = input.files[0];

  if (currentUrl) {
    URL.revokeObjectURL(currentUrl);
  }

  currentUrl = URL.createObjectURL(file);
  image.src = currentUrl;
});

Думать, что revokeObjectURL() удаляет файл

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

Быстрая памятка

  • URL.revokeObjectURL() освобождает временный blob: URL
  • метод принимает строку, созданную через URL.createObjectURL()
  • метод ничего не возвращает
  • после вызова старый blob URL больше не стоит использовать
  • исходный Blob или File не удаляется
  • не вызывайте revokeObjectURL() слишком рано
  • для изображений часто удобно вызывать метод после load
  • при замене файла освобождайте предыдущий URL перед созданием нового
  • для скачивания временный URL обычно можно освободить после клика

Коротко

URL.revokeObjectURL() нужен, чтобы убрать временную связь между blob: URL и данными в памяти браузера. Используйте его после того, как blob URL больше не нужен: после загрузки предпросмотра, после скачивания файла или перед заменой старого URL новым. Это помогает не держать лишние данные в памяти и делает работу с URL.createObjectURL() аккуратной.