Какие типы пайпов бывают в Angular и в чем разница между pure и impure пайпами?
Что проверяют
Понимаете ли вы, как пайп связан с обнаружением изменений и почему чистый пайп быстрее вызова метода в шаблоне. Следом почти всегда спрашивают: вы сделали push в массив, а пайп фильтрации ничего не пересчитал, почему.
Как отвечать
По происхождению пайпы делятся на встроенные и собственные:
- встроенные:
DatePipe,CurrencyPipe,DecimalPipe,PercentPipe,UpperCasePipe,SlicePipe,JsonPipe,KeyValuePipe,AsyncPipeи другие из@angular/common; - собственные: класс с декоратором
@Pipe({ name: 'myPipe' }), реализующийPipeTransformс методомtransform. В современных версиях пайпы standalone и подключаются прямо вimportsкомпонента.
Главное различие по поведению:
- pure (по умолчанию):
transformвызывается заново, только если изменился вход. Примитивы сравниваются по значению, объекты и массивы по ссылке. Мутация внутри массива ссылку не меняет, поэтому пересчёта не будет; - impure (
pure: false):transformвызывается на каждом цикле обнаружения изменений, даже если ничего не поменялось. Нужен, когда результат зависит от внутреннего состояния или изменений, невидимых по ссылке. Нечистые из встроенных:AsyncPipe,JsonPipe,KeyValuePipe.
AsyncPipe нечистый не случайно: он сам подписывается на Observable или Promise, отдаёт последнее значение и отписывается при уничтожении компонента, а новое значение приходит без смены ссылки на поток.
Хорошо добавить, что при работе с сигналами часть задач пайпов закрывает computed(): он пересчитывается только при смене зависимостей.
Где спотыкаются
Чинят «пайп не обновился» переводом его в impure. Правильнее не мутировать данные, а создавать новый массив: items = [...items, x].
Кладут тяжёлую работу (сортировку, фильтр по тысячам строк) в нечистый пайп. В приложении на zone.js она выполняется заново на каждый клик, таймер и ответ сервера.
Путают чистоту пайпа с тем, как часто меняются данные. Pure-пайп должен быть детерминированной функцией входа: если внутри есть обращение к сервису или текущему времени, кэш покажет устаревший результат.