“А може, замість цього використаємо пайпи?” — побачив я цей коментар у запиті на злиття, який подав лише дві години тому. Я ще не зовсім розумів усі переваги пайпів, і перша моя думка була: “Чому б просто не створити утилітну функцію?” Це зацікавило мене, і я відчув бажання розібратися глибше.
Без сумнівів, я почав шукати інформацію в Google, щоб дізнатися більше.
Поширена проблема — що не так з простою функцією
Розглянемо приклад функції, яка просто робить першу літеру імені великою.
import { Component } from '@angular/core';
import { nameList } from './random-names-list';
@Component({
selector: 'my-app',
template: `
\
\
`, styleUrls: ['./app.component.css'],
})
export class AppComponent {
names = [];
count = 0;
capitalize(name: string) {
console.log('Функція capitalize виконана: ', ++this.count);
return name.charAt(0).toUpperCase() + name.slice(1);
}
addRandomUser() {
const randomName = nameList[Math.floor(Math.random() * nameList.length)];
this.names.push(randomName);
}
}
Проблема вирішена, так? Ну, давайте подивимося на консоль, щоб дізнатися, скільки разів насправді була викликана функція, коли ми додали 3 користувачів.
Вау!! Вона була викликана 12 разів, але чому так? Це через те, як працює система виявлення змін в Angular.
Аналіз виконання
Початковий стан
- Коли компонент вперше завантажується,
names
— порожній масив. - Викликів функції
capitalize()
не відбувається, оскільки в масивіnames
немає елементів.
Перший клік кнопки
addRandomUser()
додає одне ім’я до масивуnames
(names.length = 1
).- Angular обробляє виявлення змін:
- Директива
*ngFor
перебирає оновлений масивnames
(1 елемент). - Функція
capitalize
викликається один раз.
- Директива
Загальна кількість викликів: 1
Другий клік кнопки
addRandomUser()
додає ще одне ім’я до масивуnames
(names.length = 2
).- Angular обробляє виявлення змін:
- Директива
*ngFor
перебирає оновлений масивnames
(2 елементи). - Функція
capitalize
викликається два рази (по одному для кожного імені в масиві).
- Директива
Загальна кількість викликів: 1 (попереднє) + 2 = 3
Третій клік кнопки
addRandomUser()
додає ще одне ім’я до масивуnames
(names.length = 3
).- Angular обробляє виявлення змін:
- Директива
*ngFor
перебирає оновлений масивnames
(3 елементи). - Функція
capitalize
викликається три рази (по одному для кожного імені в масиві).
- Директива
Загальна кількість викликів: 3 (попереднє) + 3 = 6
Але ось у чому секрет: Angular не зупиняється на оцінці лише одного циклу виявлення змін.
Він робить додаткові проходи, щоб забезпечити стабільність і правильність інтерфейсу користувача, що призводить до 6 додаткових викликів, в результаті чого загальна кількість викликів становить 12.
- Це дуже неефективно. Уявіть, що у вас є десятки тисяч користувачів і ви використовуєте цю утилітарну функцію.
- Це призведе до дублювання коду, адже вам, можливо, знадобиться та сама функція
capitalize
, щоб відобразити інші дані. - Навіть якщо ви перемістите цей код в сервіс, проблема залишиться.
Ось тут і з’являється Pipe. Він забезпечує повторне використання і не впливає на продуктивність.
Ось той самий код, але з використанням pipes.
// файл capitalize.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'capitalize',
})
export class CapitalizePipe implements PipeTransform {
count = 0;
transform(name: string): string {
console.log('Функція capitalize виконана: ', ++this.count);
return name.charAt(0).toUpperCase() + name.slice(1);
}
}
// файл app.component.ts
import { Component} from '@angular/core';
import { nameList } from './random-names-list';
@Component({
selector: 'my-app',
template: `
\
\
{{ name | capitalize }}\ \ \ДОДАТИ КОРИСТУВАЧА\ `, styleUrls: ['./app.component.css'], }) export class AppComponent { names = []; addRandomUser() { const randomName = nameList[Math.floor(Math.random() * nameList.length)]; this.names.push(randomName); } }
Тепер можна побачити, що кількість викликів зменшилася з 6 до 3.
Якщо ви додасте 7 користувачів до списку, то при використанні функції буде здійснено 56 викликів, а при використанні pipe — лише 7.
“Звісно, ми можемо використати pipes для цього” — відповів я на коментар і внес зміни.
Якщо хочете більше таких історій, ставте лайк і підписуйтесь 🙂
Перекладено з: Why Angular Pipes Outshine Functions for Data Transformation