HTTP — Оптимизация взаимодействия с сервером с помощью дебаунсинга¶
27.02.2023
Если вам нужно сделать HTTP-запрос в ответ на ввод пользователя, неэффективно отправлять запрос на каждое нажатие клавиши. Лучше подождать, пока пользователь перестанет набирать текст, а затем отправить запрос. Эта техника известна как дебаунсинг.
Реализация дебаунсинга¶
Рассмотрим следующий шаблон, который позволяет пользователю ввести поисковый запрос, чтобы найти пакет по имени. Когда пользователь вводит имя в поле поиска, PackageSearchComponent
отправляет запрос на поиск пакета с таким именем в API поиска пакетов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Здесь привязка события keyup
отправляет каждое нажатие клавиши в метод search()
компонента.
Тип $event.target
в шаблоне только EventTarget
. В методе getValue()
цель приводится к HTMLInputElement
, чтобы type-safe имел доступ к ее свойству value
.
1 2 3 |
|
Следующий фрагмент реализует дебаггинг для этого входа с помощью операторов RxJS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Текст searchText$
— это последовательность значений поля поиска, поступающих от пользователя. Он определен как RxJS Subject
, что означает, что это многоадресный Observable
, который также может выдавать значения для себя, вызывая next(value)
, как это происходит в методе search()
.
Вместо того, чтобы направлять каждое значение searchText
непосредственно в инжектированный PackageSearchService
, код в ngOnInit()
направляет значения поиска через три оператора, так что значение поиска достигает сервиса, только если это новое значение и пользователь остановил ввод.
Операторы RxJS | Подробности |
---|---|
debounceTime(500) | Ждать, пока пользователь не перестанет набирать текст, что в данном случае составляет ½ секунды. |
distinctUntilChanged() | Подождите, пока текст поиска не изменится. |
switchMap() | Отправляем запрос на поиск в службу. |
Код устанавливает packages$
в этот перекомпонованный Observable
результатов поиска. Шаблон подписывается на packages$
с помощью AsyncPipe и отображает результаты поиска по мере их поступления.
Подробнее об опции withRefresh
смотрите в Использование перехватчиков для запроса нескольких значений.
Использование оператора switchMap()
¶
Оператор switchMap()
принимает аргумент функции, которая возвращает Observable
. В примере PackageSearchService.search
возвращает Observable
, как и другие методы службы данных.
Если предыдущий запрос на поиск все еще находится в полете, например, при плохом сетевом соединении, оператор отменяет этот запрос и посылает новый.
switchMap()
возвращает ответы сервиса в исходном порядке запроса, даже если сервер возвращает их не по порядку.
Если вы думаете, что будете использовать эту логику дебаггинга повторно, подумайте о том, чтобы перенести ее в служебную функцию или в сам PackageSearchService
.