Уменьшение HTTP-запросов в приложении angular 2

N.B. В этом посте предполагается, что вы знакомы с HTTP-сервисом angular, асинхронным конвейером и немного Rxjs.

Если вы, как и я, делаете первые шаги с angular 2 и устрашающим новым миром наблюдаемых, то в следующем посте будет описана эффективная стратегия взаимодействия с API с использованием HTTP-сервиса angular.

Прежде чем мы начнем, мне нужно кое-что прояснить. Я не эксперт по рецептам. Я не Бен Леш или Андре Стальц. Отнюдь не. Я только начинаю свое путешествие в волшебный мир реактивного программирования и, чтобы правильно подытожить, где я нахожусь в этом путешествии, вот маленький жираф.

Итак, давайте установим сцену. У меня есть служба мастера, которая отправляется в конечную точку мастера в API и извлекает некоторые данные. Компонент потребляет данные и выводит их в представление. Довольно стандартный материал.

Наша служба возвращает наблюдаемый объект нашему компоненту, который мы затем потребляем в нашем представлении через асинхронный конвейер. Нет необходимости подписываться на наблюдаемое, поскольку асинхронный конвейер позаботится об этом за нас, делая наш компонент чистым и экономичным.

Все выглядит круто, правда? На первый взгляд да, но загляните внутрь вкладки сети в своих инструментах разработчика, и вы увидите вызов API для каждой подписки на наблюдаемое.

Что за выдумка! Это просто не годится. Почему так много запросов?

Ответ, как ни странно, заключается в температуре наблюдаемого. Да, я сказал температуру. Наблюдаемые можно охарактеризовать как горячие или холодные. Я не буду вдаваться в подробности о разнице между ними, поскольку это видео Андре Стальца объясняет лучше, чем я.

По умолчанию наблюдаемый объект, возвращаемый HTTP-службой angular, является холодным, и это причина наших многочисленных запросов. Когда вы подписываетесь на холодное наблюдение, мы каждый раз создаем новый поток. Соедините это с асинхронным конвейером, и мы неосознанно настраиваем несколько подписок / потоков и, в конечном итоге, HTTP-запросы в нашем компоненте.

Чтобы решить эту проблему, мы должны добавить немного тепла в нашу наблюдаемую. Один из способов добиться этого - использовать оператор share, предоставляемый библиотекой Rx.

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

Так лучше, но все еще недостаточно. Мы по-прежнему получаем несколько запросов на одни и те же данные. Это происходит из-за поздних подписок, исходящих из условия *ngIf в нашем шаблоне, а также из-за того, что мы регистрируем нового подписчика в обработчике нажатия кнопки. Оказывается, share не любит пунктуальность и не любит опоздавших подписчиков. Что нам действительно нужно, так это иметь возможность кэшировать значение из первоначального HTTP-вызова и воспроизводить его для всех подписок, независимо от того, когда они подписываются.

publishReplay(1).refCount() на победу.

Оператор publishReplay заботится о кэшировании всех испускаемых значений из наблюдаемого потока и воспроизведении их для любых подписчиков независимо от того, когда они подписываются. Передача значения 1 гарантирует, что кэшируется только последнее переданное значение, а refcount () просто позаботится о подключении к / от наблюдаемого.

Теперь, если мы посмотрим на нашу вкладку сети, у нас будет только один запрос для всех наших подписок.

Теперь готовим на газе. :-)