W3docs

Загрузка ресурсов в JavaScript: onload и onerror

Как события onload и onerror отслеживают загрузку изображений, скриптов и стилей — с примерами и стратегиями резервного поведения.

Внешние ресурсы — изображения, скрипты, стили, iframe — загружаются асинхронно и независимо от кода JavaScript, который их запрашивает. Браузер начинает загрузку, а ваш код продолжает выполняться; ресурс может быть не готов ещё несколько миллисекунд или секунд. Чтобы узнать, когда ресурс готов (или что загрузка завершилась ошибкой), каждый загружаемый элемент генерирует два события: load при успехе и error при неудаче. На этой странице показано, как использовать их через свойства-обработчики onload / onerror.

Это тесно связано с жизненным циклом страницы, рассмотренным в разделе DOMContentLoaded, load, beforeunload, unload, а также со стратегиями загрузки скриптов из раздела Скрипты: async, defer.

Обработка загрузки ресурсов с помощью события onload

Что такое событие onload?

Событие load срабатывает на элементе, когда его ресурс полностью загружен и готов к использованию. Подписаться на него можно двумя равнозначными способами:

// 1. Handler property (only one handler allowed)
img.onload = () => { /* ... */ };

// 2. addEventListener (multiple handlers allowed)
img.addEventListener('load', () => { /* ... */ });

Форма через свойство (onload) удобна, но допускает лишь один обработчик — при новом присвоении предыдущий перезаписывается. Предпочитайте addEventListener('load', ...), если несколько частей кода должны реагировать на один и тот же ресурс.

Важный момент: для <img> событие load охватывает только байты конкретного изображения. Это не страничный window.onload, который ждёт всех ресурсов. Не путайте их.

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

Рассмотрим сценарий, при котором изображение нужно показать только после полной загрузки, чтобы не выводить частичное или сломанное изображение.

<div>Here you see the w3docs logo when the page is loaded.</div>
<br />
<div id="imageContainer" style="background-color: grey;"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
    var img = new Image();
    img.onload = function() {
        document.getElementById('imageContainer').appendChild(img);
    };
    img.src = 'https://www.w3docs.com/build/images/logo-color-w3.png';
});
</script>

Этот скрипт гарантирует, что изображение будет добавлено в #imageContainer только после полной загрузки, что улучшает пользовательский опыт и предотвращает отображение незагруженного изображения.

Внимание

Устанавливайте img.onload до img.src. Браузер может отдать кешированное изображение так быстро, что загрузка завершится в том же тике, в котором присваивается src — если обработчик ещё не прикреплён, событие будет пропущено.

Использование события onerror для обработки ошибок

Что такое событие onerror?

Событие onerror необходимо для надёжной веб-разработки. Оно срабатывает, когда при загрузке внешнего ресурса — скрипта или изображения — возникает ошибка. Это событие критически важно для корректной обработки ошибок и поддержания непрерывного пользовательского опыта.

Пример: обработка ошибки загрузки изображения

Рассмотрим сценарий, при котором изображение не загружается из-за битой ссылки или проблемы с сервером. С помощью события onerror можно предоставить резервное решение или уведомить пользователя. В следующем примере битый src немедленно запускает обработчик ошибки, поскольку ссылка не указывает на реальный файл.

Ресурс генерирует либо load, либо error, но никогда оба сразу. Поэтому можно прикрепить обработчики для каждого и быть уверенным, что сработает ровно один.

<div>If there was no error, you could see an image below. But it's a broken link!</div>
<br />
<div id="imageContainer" style="background-color: grey;"></div>
<script>
const img = new Image();
const imageContainer = document.getElementById('imageContainer');
img.onerror = function() {
    imageContainer.innerHTML = 'An error happened.';
};
img.onload = function() {
    imageContainer.appendChild(img);
};
img.src = 'https://www.w3docs.com/build/images/broken-link.png';
</script>

В этом примере при неудачной загрузке изображения контейнер показывает резервное сообщение вместо иконки сломанного изображения, прозрачно обрабатывая ошибку.

Информация

onerror срабатывает только при ошибках ресурса — ответ 404, заблокированный запрос, ошибка DNS или повреждённый файл. Оно не срабатывает, если загруженный скрипт выбрасывает исключение во время выполнения; такие ошибки перехватывает глобальный обработчик window.onerror / window.addEventListener('error', ...).

Пример: загрузка скрипта или стилей

Тот же шаблон применим к элементам <script> и <link>. Их можно создавать динамически и прикреплять обработчики onload/onerror:

<script>
function loadScript(url) {
    const script = document.createElement('script');
    script.src = url;
    script.onload = () => console.log('Script loaded successfully');
    script.onerror = () => console.error('Failed to load script');
    document.head.appendChild(script);
}
loadScript('https://example.com/app.js');

function loadStylesheet(url) {
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = url;
    link.onload = () => console.log('Stylesheet loaded successfully');
    link.onerror = () => console.error('Failed to load stylesheet');
    document.head.appendChild(link);
}
loadStylesheet('https://example.com/styles.css');
</script>

Динамически созданные скрипты ведут себя как async-скрипты: они загружаются параллельно и выполняются сразу по завершении загрузки, поэтому порядок их выполнения не гарантирован. Если один скрипт зависит от другого, цепочку вызовов нужно выстраивать внутри onload первого скрипта.

Пример: оборачивание load/error в Promise

В современном коде удобно обернуть оба события в Promise, что даёт синтаксис async/await и единое место для обработки ошибок:

function loadScript(src) {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = src;
    script.onload = () => resolve(script);
    script.onerror = () => reject(new Error(`Failed to load: ${src}`));
    document.head.append(script);
  });
}

// Usage
loadScript('https://example.com/app.js')
  .then(() => console.log('Ready to use the script'))
  .catch((err) => console.error(err.message));

Поскольку load и error взаимно исключают друг друга, Promise завершается ровно один раз — либо успешно, либо с ошибкой.

Оптимизация веб-производительности через обработку событий

Оптимизация веб-производительности предполагает управление последовательностью загрузки ресурсов и корректную обработку сбоев. События onload и onerror особенно ценны при динамическом подключении ресурсов. Вместо того чтобы прописывать все ресурсы в HTML напрямую, можно загружать некритичные из них по требованию. Когда ресурс не загружается, срабатывает onerror, позволяя реализовать резервную логику — например, заменить сломанное изображение заглушкой или повторить неудавшийся запрос скрипта. Сочетая эти события с прогрессивным рендерингом, вы обеспечиваете мгновенное появление ключевого контента, пока второстепенные ресурсы загружаются в фоне, поддерживая плавный пользовательский опыт даже при слабом соединении.

Заключение

Понимание событий onload и onerror в JavaScript и умение их применять — это основа работы любого веб-разработчика, стремящегося повысить надёжность и производительность своих приложений. Грамотное использование этих событий позволяет эффективно управлять ресурсами, улучшая как производительность, так и пользовательский опыт. Приведённые примеры служат отправной точкой для реализации этих техник в различных сценариях и способствуют более глубокому освоению механизмов загрузки ресурсов в JavaScript.

Практика

Практика
Какие утверждения о событиях 'onload' и 'onerror' верны?
Какие утверждения о событиях 'onload' и 'onerror' верны?
Was this page helpful?