Асинхронная загрузка изображений

Идея в том, чтобы загружать изображения вне DOM. По-умолчанию показывается прелоадер, а по окончанию загрузки подменяется ссылка на изображение. Так как изображение попадает в кэш браузера, то оно мгновенно появиться у пользователя.

  /**
   * Загрузить изображение асинхронно
   * @param url - image URL
   */
  private _asyncImage(url: string): Promise<HTMLImageElement> {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(img);
      img.onerror = () => reject(new Error(`Could not load image: ${url}`));
      img.src = url;
    });
  }

  /**
   * Проверить успешность загрузки изображения.
   * @param img - загружаемое изображения
   */
  private _isImageLoaded(img: HTMLImageElement): boolean {
    if (!img.complete) {
      return false;
    }
    if (img.naturalWidth + img.naturalHeight === 0) {
      return false;
    }
    return true;
  }  

Использование

this._asyncImage(value)
  .then(img => {
    this._isImageLoaded(img) ? this._setBackgroundImage(value) : this._setDefaultImage();
  })
  .catch(() => this._setDefaultImage());

В методах _setDefaultImage и _setBackgroundImage в зависимости от ситуации происходит подмена:

  • src для <img>
  • url() для background-image

Похожие записи

+function ($) { "use strict"; }(window.jQuery);

  • объявляется IIFE (немедленно выполняемая функция-выражение)
  • в функцию передаётся объект библиотеки jQuery, которая внутри будет доступна через переменную с именем $
  • включается «строгий режим»