Уменьшение 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 () просто позаботится о подключении к / от наблюдаемого.
Теперь, если мы посмотрим на нашу вкладку сети, у нас будет только один запрос для всех наших подписок.
Теперь готовим на газе. :-)