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

Идея в том, чтобы загружать изображения вне 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 url - image URL
   */
  private loadImageAsync(url: string): Observable<HTMLImageElement> {
    return new Observable(observer => {
      const img = new Image();
      img.onload = () => {
        observer.next(img);
        observer.complete();
      };
      img.onerror = () => observer.error(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, которая внутри будет доступна через переменную с именем $
  • включается «строгий режим»

RxJs Subjects

Выдержки из доклада Андрея Алексеева (Tinkoff) про RxJs (Subject, Behaviour Subject, Replay Subject, Async Subject). Применение в Angular.

Не ставить фокус по клику

Проблема заключалась в следующем: когда имеется интерактивный элемент с :focus стилем и вы щелкаете по этому элементу, на нём остаётся focus стиль (outline обводка). У нативной кнопки всё работает as expected, но стоит её добавить любой стиль и, как побочный эффект, меняется её поведение.