Угловая производительность — фильтр против функционального выражения

У меня есть вопрос о производительности для Angular 1.x. Есть ли какие-либо преимущества в производительности для использования функциональных выражений по сравнению с фильтрами для получения значений на основе ключей? Поясню на примерах.

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

E.g. {{ ID123 | getField:'object':'field'}}

Затем пользовательский фильтр выполнит асинхронный вызов (в БД), чтобы получить имя объекта, которое я укажу на основе ключа (ID123), и вернуть указанное поле (вместо того, чтобы просто показывать ключ).

В настоящее время я занимаюсь некоторой очисткой производительности и много читал о том, как избегать фильтров, поскольку они сильно влияют на производительность. Одна вещь, которую я делаю, это использование одноразовых привязок {{::ID123 | getField:'object':'field'}}, но в некоторых сценариях я не могу этого сделать (поскольку мне нужно обновить значение).

Затем я смотрел на функциональные выражения вместо пользовательских фильтров, например. {{getField(ID123,'object','field')}}. Но я не уверен, что это даст какие-либо преимущества в производительности.

Вы можете увидеть мой пример plunker, где я сравниваю их.

https://plnkr.co/edit/hlL2LSOGjq5HsImUyqyu?p=preview

Будут ли какие-либо преимущества в производительности? Также есть ли способ проверить или сравнить разницу между ними?

Спасибо


person Anand Patel    schedule 27.06.2016    source источник
comment
есть ли способ проверить разницу между ними... Есть много вопросов о том, как это сделать, включая это один о переполнении стека. Относительно того, какие преимущества производительности существуют? Поскольку вы выполняете асинхронный вызов при каждом вызове фильтра или функции, я предполагаю, что фильтр или функция не являются вашим узким местом; это асинхронный вызов. Вам следует подумать о реструктуризации ваших запросов, чтобы информация поступала сразу.   -  person Heretic Monkey    schedule 28.06.2016
comment
Убедитесь, что вы понимаете, как работают циклы дайджеста. В каждом цикле можно сделать много дайджестов. Выполнение асинхронных вызовов для каждого дайджеста вообще неэффективно.   -  person charlietfl    schedule 28.06.2016
comment
Я кэширую асинхронные вызовы, поэтому каждый цикл дайджеста проверяет кеш и делает асинхронный вызов только в том случае, если кеша нет. Что касается производительности, меня больше беспокоит количество дайджест-вызовов, которые вызывают фильтры. На некоторых страницах есть 20-30 таких фильтров. Таким образом, во время цикла дайджеста они все вызываются. Вызываются ли функции также при каждом цикле дайджеста?   -  person Anand Patel    schedule 28.06.2016
comment
Поэтому я добавил счетчик на фильтр и функцию. Похоже, функция вызывается почти в 10 раз чаще, чем фильтр. plnkr.co/edit/IoxmBjGQEB81lwoSc0iz?p=preview   -  person Anand Patel    schedule 28.06.2016


Ответы (1)


Короткий ответ: фильтр лучше, если он идемпотентный (т. е. один и тот же ввод всегда возвращает один и тот же вывод) и ввод не является объектом.


Длинный ответ:

Если вы используете функцию, она будет вызываться в каждом цикле дайджеста, потому что Angular должен проверять, одинаковы ли выходные данные. Это означает, что он будет вызываться несколько раз, прежде чем отображаемые данные «установятся».

Если вы используете фильтр, а ввод не является объектом, он будет выполнен только в том случае, если ввод изменился, поскольку Angular предполагает, что фильтры являются идемпотентными, если только их свойство $stateful не установлено на true. Объекты являются исключением из этого правила, потому что проверка того, изменились ли глубокие свойства объектов, обходится дорого, поэтому Angular выполняет фильтр в каждом цикле дайджеста, что делает его таким же, как функция.

Будьте осторожны с созданием пользовательских фильтров, которые не являются идемпотентными, Angular предположит, что они идемпотентны, и не обновит отображаемые данные должным образом. Если вы должны создать его, отметьте их как $stateful.


Источники

Этот вопрос связан и указал мне правильное направление:
Пользовательский фильтр и функция фильтрации в сравнении производительности контроллера

А это документация Angular для фильтров (разделы «При выполнении фильтров» и «Фильтры с отслеживанием состояния»):
https://docs.angularjs.org/guide/filter

person QOI    schedule 22.02.2017