Наивная бесконечная прокрутка в реактивном программировании с использованием наблюдаемых RxJS

Простой эксперимент по реализации бесконечной прокрутки с помощью RxJS

Сообщение в блоге о реализации Angular: Директива Simple Infinite Scroller с помощью RxJS Observables

Что такое реактивное программирование?
Проще говоря, это программирование с использованием асинхронных потоков данных. Есть отличный пост от Andre Staltz - Введение в реактивное программирование, которого вам не хватало, в сопровождении видео на egghead.io.

Введение в реактивное программирование, которого вам не хватало

Https://egghead.io/courses/introduction-to-reactive-programming

Что такое RxJS?

RxJS или Reactive Extensions - это библиотека, разработанная Microsoft Open Technologies на Javascript для преобразования, составления и запросов потоков данных. Https://github.com/Reactive-Extensions/RxJS

Бен Леш сделал отличный доклад на тему Реактивное мышление с RxJS 5.

Ниже приведены несколько хороших знакомств с Observables и несколько операторов от Netanel Basal.

  1. Наблюдения под капотом.
  2. RxJS - Шесть операторов, которые вы должны знать

Что мы будем строить?

Мы собираемся построить наивный бесконечный скроллер, используя наблюдаемые. Всякий раз, когда пользователь прокручивает данный контейнер до 70%, мы запускаем вызов api для получения дополнительных данных с сервера. Для этой реализации мы будем использовать неофициальный api HackerNews, чтобы получать последние новости.

Ниже приведены операторы, которые мы будем использовать из RxJS.

  1. map: аналогично отображению в массиве, отображение потока входящих данных.
  2. filter: аналогично фильтру в массиве, фильтрует поток входящих данных.
  3. pairwise: возвращает массив текущих переданных данных, а также ранее переданных данных.
  4. startWith: возвращает наблюдаемое, испускает предоставленные значения перед тем, как испускать значения из наблюдаемого источника
  5. exhaustMap: ожидает передачи значения, пока не завершится переданный внутренний наблюдаемый объект

Ссылка на вывод в jsbin.com: https://output.jsbin.com/punibux

# Phase1 - настройка базового HTML и стилей.

Импортируйте библиотеку RxJS, и мы будем использовать infinite-scroller в качестве контейнера прокрутки и добавлять к нему новости.

# Phase2 - настройка вспомогательных функций для обработки данных, рендеринга и вычислений.

Первые три функции просты,

  1. getQuotesAPI - возвращает URL-адрес API с номером текущей страницы в качестве параметра запроса
  2. processData - обрабатывает возвращаемые данные из api, что выполняется с помощью fetch API и увеличивает currentPage.
  3. renderNews - берет каждую новость и отображает ее в представлении.

Следующие две функции используются для вычислений прокрутки.

4. isUserScrollingDown - определяет, прокручивает пользователь вниз или нет.

5. isScrollExpectedPercent - определяет, прокрутил ли пользователь до переданного процента, чтобы получить больше данных.

# Phase3 - настройка наблюдаемого потока

Чтобы фиксировать события прокрутки в контейнере, нам нужно создать наблюдаемый из события прокрутки. Этого можно добиться с помощью Rx.Observable.fromEvent- docs. Это соглашение о добавлении $ к переменной при обращении к наблюдаемому потоку.

# Phase4 - логика потока для обработки событий прокрутки и вызова API

Мы собираемся взять событие прокрутки, генерируемое scrollEvent$ и map, чтобы принять только те значения, которые нам нужны для нашей логики бесконечной прокрутки. Нам нужно всего три свойства из элемента scroll - scrollHeight, scrollTop и clientHeight.

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

Теперь мы можем взять пару позиций и передать ее filter им для фильтрации в соответствии с нашими условиями.

  1. Прокручивает ли пользователь вниз
  2. Достигнуто ли прокруткой пользователя семьдесят процентов контейнера

requestOnScroll$ - вызывается, когда userScrollDown$ проходит условия фильтрации. Начнем с начального значения пустого массива.

Мы собираемся использовать Rx.Observable.fromPromise для создания наблюдаемого из обещания. fetch выполняет HTTP-вызов и возвращает обещание. exhaustMap будет ждать завершения выборки, а внутренний наблюдаемый объект выдаст данные из API.

Observables ленивы - это означает, что они ничего не делают, пока вы на них не подпишетесь. Мы подпишемся на requestOnScroll$ и передадим processData методу подписки. Когда exhaustMap передает данные из API, они передаются processData, который вызывает renderNews для рендеринга в представлении.

Ниже показано изображение бесконечной прокрутки в действии, обратите внимание на полосу прокрутки справа.

В своем следующем посте я попытаюсь реализовать это в Angular 2, создав директиву бесконечной прокрутки.

Обновление: вот ссылка на мой последующий пост о Директиве Simple Infinite Scroller с RxJS Observables