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

Как понять что загрузились все ресурсы?

2.0 Middle🔥 182 комментариев
#JavaScript Core

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

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

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

Проверка полной загрузки всех ресурсов

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

События загрузки страницы

Основные события жизненного цикла загрузки:

// 1. DOMContentLoaded - DOM построен, но не все ресурсы загружены
document.addEventListener('DOMContentLoaded', () => {
  console.log('DOM готов, можно работать с элементами');
  // Скрипты, стили и изображения могут ещё загружаться
});

// 2. Load - все ресурсы загружены (iframe, изображения, стили, скрипты)
window.addEventListener('load', () => {
  console.log('Все ресурсы загружены');
  // Теперь безопасно обращаться ко всем элементам
});

// 3. beforeunload - перед закрытием страницы
window.addEventListener('beforeunload', () => {
  console.log('Пользователь закрывает страницу');
});

Проверка состояния документа

Свойство document.readyState показывает текущее состояние загрузки:

// Состояния readyState:
// "loading" - документ загружается
// "interactive" - загрузка завершена, но ресурсы загружаются
// "complete" - все ресурсы загружены

function waitForFullLoad() {
  return new Promise(resolve => {
    if (document.readyState === 'complete') {
      resolve();
    } else {
      window.addEventListener('load', resolve);
    }
  });
}

// Использование
await waitForFullLoad();
console.log('Страница полностью загружена');

Performance API для отслеживания ресурсов

Modern способ - использовать PerformanceObserver:

// Отслеживание загрузки конкретных ресурсов
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.initiatorType === 'script') {
      console.log('Скрипт загружен:', entry.name, entry.duration, 'ms');
    } else if (entry.initiatorType === 'link') {
      console.log('Стиль загружен:', entry.name);
    } else if (entry.initiatorType === 'img') {
      console.log('Изображение загружено:', entry.name);
    }
  }
});

observer.observe({ entryTypes: ['resource'] });

Проверка загрузки изображений

// Проверка, загружены ли все изображения на странице
async function waitForAllImages() {
  const images = document.querySelectorAll('img');
  const promises = Array.from(images).map(img => {
    return new Promise((resolve, reject) => {
      if (img.complete && img.naturalHeight !== 0) {
        // Изображение уже загружено
        resolve();
      } else {
        img.addEventListener('load', resolve);
        img.addEventListener('error', reject);
        setTimeout(() => reject(new Error('Timeout')), 10000);
      }
    });
  });
  
  return Promise.all(promises);
}

// Использование
try {
  await waitForAllImages();
  console.log('Все изображения загружены');
} catch (error) {
  console.error('Ошибка загрузки изображений:', error);
}

Проверка загрузки шрифтов

// FontFaceSet API - проверка загрузки шрифтов
if (document.fonts) {
  document.fonts.ready.then(() => {
    console.log('Все шрифты загружены');
    // Переотрисуем элементы, если нужно
  });
}

// Альтернатива для старых браузеров
async function waitForFonts() {
  if (!document.fonts) return;
  
  try {
    await document.fonts.ready;
    console.log('Шрифты готовы');
  } catch (error) {
    console.error('Ошибка при загрузке шрифтов:', error);
  }
}

Комплексная проверка всех ресурсов

// Функция ждёт полной загрузки всего
async function waitForCompleteLoad() {
  // Ждём, пока документ будет готов
  await new Promise(resolve => {
    if (document.readyState === 'complete') {
      resolve();
    } else {
      window.addEventListener('load', resolve);
    }
  });
  
  // Ждём шрифтов
  if (document.fonts) {
    await document.fonts.ready;
  }
  
  // Ждём изображений
  await waitForAllImages();
  
  // Небольшая задержка для финальной отрисовки
  await new Promise(resolve => requestAnimationFrame(resolve));
  
  console.log('Все ресурсы полностью загружены');
}

// Использование
try {
  await waitForCompleteLoad();
  console.log('Страница готова к работе');
} catch (error) {
  console.error('Ошибка при загрузке:', error);
}

Web Vitals для мониторинга загрузки

// Google Web Vitals
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

getCLS(console.log); // Cumulative Layout Shift
getFID(console.log); // First Input Delay
getFCP(console.log); // First Contentful Paint
getLCP(console.log); // Largest Contentful Paint
getTTFB(console.log); // Time to First Byte

// Это показывает, насколько хорошо загружается страница

Практический пример для React

import { useEffect, useState } from 'react';

function useLoadingComplete() {
  const [isLoaded, setIsLoaded] = useState(false);
  
  useEffect(() => {
    const checkLoading = async () => {
      if (document.readyState === 'complete') {
        setIsLoaded(true);
      } else {
        await new Promise(resolve => window.addEventListener('load', resolve));
        setIsLoaded(true);
      }
    };
    
    checkLoading();
  }, []);
  
  return isLoaded;
}

// Использование
function App() {
  const isLoaded = useLoadingComplete();
  
  return (
    <div>
      {!isLoaded && <Skeleton />}
      {isLoaded && <MainContent />}
    </div>
  );
}

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