Pull to refresh
5
-0.2
Andrei Shpileuski @andreishpileuski

Sr. Angular Dev · Team/Tech lead · Web Auditor

Send message

withComponentInputBinding()
Упрощение работы с параметрами маршрутизатора в Angular.

Как было раньше?

  1. Создаем переменную/свойство (Signal, BehaivorSubject, Observable, неважно)

  2. Инжектим и подписываемся на ActivatedRoute

  3. Получаем параметры маршрута

  4. Записываем в BS/Signal

😵‍💫😵‍💫😵‍💫

Манипуляций довольно много, но мы все к этому привыкли и это кажется нормальным.

Но с withComponentInputBinding() все стало намного проще:
1. Создаем сигнальный инпут... и...
Вот и все!

Никаких дополнительных манипуляций, и значение «у вас в кармане». Все, что вам нужно, чтобы это работало, — это передать withComponentInputBinding() в качестве аргумента в provideRouter().

Функция не новая (кажется, появилась в Angular 16), но я редко ее видел в проектах.

Немного технической информации из документации:

🔍Маршрутизатор передает данные в input() из:

  1. Параметров запроса (?page=1&sort=asc)

  2. Параметров пути и матрицы (/users/123;details=true)

  3. Статических данных маршрута (data: { role: 'admin' })

  4. Результатов резолвера (resolve: { user: userResolver })

🔍 Приоритеты:
Если есть дублирующиеся ключи, данные переопределяются в порядке выше — резолверы имеют наивысший приоритет и перезапишут остальные.

🚩 Важный нюанс
Если в маршруте нет данных для input(), он получит undefined (например, если параметр запроса удален из URL).

ℹ️ Как задать значения по умолчанию?

✔ Через resolver (чтобы данные всегда были в маршруте)
✔ Через transform в input() (если нужно обрабатывать undefined)

Спасибо разработчикам Angular за эту функциональность 🙏.

Больше об 🅰️ngular в моём Telegram-канале

Tags:
-1
Comments0

🦥 RxJS defer — ленивая инициализация Observable

defer — это фабрика, которая создает Observable только при подписке, а не во время объявления. Идеально подходит для:

  • HTTP-запросов (чтобы избежать преждевременного выполнения)

  • динамических данных (которые должны быть свежими при каждой подписке)

  • условных потоков (когда Observable зависит от состояния времени выполнения)

📌 Основные варианты использования

  1. Свежие данные при каждой подписке

    const freshData$ = defer(() => of(Date.now()));

    // Новая временная метка при каждой подписке()

  2. Работа с изменяемым состоянием

    const token$ = defer(() => of(localStorage.getItem('token')));

    // Всегда получает текущий токен, даже если обновлен

  3. Условные наблюдаемые

    const api$ = defer(() => isLoggedIn ? http.get('/user') : http.get('/guest') );

  4. Генерация случайного значения

    const random$ = defer(() => of(Math.random()));

    // Новое случайное число на подписку

🚫 Ограничения defer

  • нет кэширования → используйте shareReplay, если вам нужно повторно использовать результаты.

  • нет отмены запроса → объедините с switchMap/takeUntil для управления отменой

⚡Когда следует выбирать defer вместо обычных наблюдаемых?

  • данные должны быть свежими при каждом subscribe()

  • cоздание наблюдаемого стоит дорого и должно быть отложено

  • поток зависит от изменяемых условий (флаги функций, статус аутентификации и т. д.)

Больше об 🅰️ngular в моём Telegram-канале

Tags:
0
Comments0

😎 Кастомный signal в Angular

Мы, как разработчики, использующие в работе самый крутой фреймворк (по моему мнению🙂), немного избалованы обилием его возможностей, особенно в последнее время. Но иногда хочется либо побаловаться, либо возникает реальная потребность в функционале, которого нет, но очень хотелось бы. 


И вот, как-то я в очередной раз писал подобные строки:

isOpened = signal(false);

toggle() {

  this.isOpened.update(value => !value);

}


#isOpenedEffect = effect(() => {

  console.log('New state:', this.isOpened())

})

- и подумал: 'Было бы удобно, если бы был булевый signal с методом toggle'


В этом не было прям сильной необходимости, однако было бы немного удобнее (процентов на 10 😅). И появилась идея написать свой сигнал (реализация на фото)


Пример, согласен, так себе. 

👍🏼 меньше кода, более аккуратно

👎🏼 всей команде придется подстроится


Но этим постом я просто хотел показать, что есть такая возможность создания своего переиспользуемого сигнала под нужды вашего проекта, где это будет выглядеть уместно и целесообразно. 

💬 А какого сигнала не хватает вам?

Больше об 🅰️ngular в моём Telegram-канале

Tags:
0
Comments3

RxJS: Почему shareReplay(1) может вызывать утечки памяти

Если вы используете shareReplay(1) в RxJS, будьте осторожны — в некоторых случаях это может привести к утечкам памяти! Давайте разберёмся, почему так происходит и как это исправить.

❌ Проблема с shareReplay(1). По умолчанию:

  • Сохраняет последнее значение в бесконечном буфере, даже если подписчиков больше нет

  • Не отписывается от источника, когда никто не слушает (например, interval, Subject, HTTP-запросы)
    Это означает, что данные могут накапливаться, а ненужные Observable продолжают работать в фоне

✅ Решение: shareReplay({ bufferSize: 1, refCount: true })

  • Добавление refCount: true решает проблему:

  • Автоматически отписывается, когда не остаётся подписчиков

  • Очищает буфер, предотвращая утечки памяти

💡 Ключевые выводы:

  1. shareReplay(1) - Может оставлять "висящие" подписки

  2. shareReplay({ bufferSize: 1, refCount: true }) - Безопасная альтернатива

Я обнаружил эту проблему во время code review вчера, а впервые узнал о ней из видео Dmytro Mezhenskyi.

🔗 P.S. Самое время быстро исправить это в наших проектах!)

Больше об 🅰️ngular в моём Telegram-канале

Tags:
0
Comments0

"mergeMap: Секрет управления параллелизмом в RxJS"

Вы знаете mergeMapconcatMapexhaustMap и switchMap — но знали ли вы, что только один из них принимает второй аргумент?

👉 mergeMap уникален благодаря параметру concurrent, который ограничивает параллельные подписки. Это как "регулятор скорости" для ваших Observable.

_____

Пример использования (контролируемая загрузка файлов):

Представьте, что вам нужно:
1️⃣ Обработать несколько файлов
2️⃣ Избежать перегрузки браузера/API
3️⃣ Сохранить порядок загрузки

В этом случае второй аргумент mergeMap становится незаменимым:

from(fileList).pipe(
  mergeMap(
    file => uploadFile(file), // функция загрузки
    3                        // одновременно только 3 файла
  )
).subscribe();

_____

Преимущества mergeMap с concurrent:
✅ Предотвращает перегрузку API
✅ Оптимизирует нагрузку на сеть
✅ Сохраняет отзывчивость интерфейса
_____

Знали ли об этой возможности? 😉

Больше об Angular в телеграмм-канале

Tags:
0
Comments0

Управление методами в зависимости от окружения в 🅰️ngular

Бывают случаи, когда нужно, чтобы определенные методы работали только:

  • 🛠️ В dev-режиме (например, фича-тогглы, дебаг-логи, экспериментальные функции)

  • 🚀 В prod-режиме (аналитика, мониторинг, продакшен-логика)

Вместо того чтобы писать if (isDevMode()) {...} везде, можно использовать декораторы Angular для более чистого и декларативного подхода.

_____

Одно из решений:

export function EnvMode(mode: 'dev' | 'prod') { return function (_: unknown, __: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; descriptor.value = function (...args: unknown[]) { const shouldExecute = mode === 'dev' ? isDevMode() : !isDevMode(); if (!shouldExecute) return; return originalMethod.apply(this, args); }; return descriptor; }; }

_____

Как использовать:

@EnvMode('dev') public setFeatureToggle(): void { // Сработает только в dev-режиме } @EnvMode('prod') public sendAnalytics(): void { // Сработает только в prod-режиме }

_____

🤔 А вы создавали кастомные декораторы? Зачем?

Больше про Angular в тг канале

Tags:
0
Comments0

Angular Hack: Цикл без данных (в тэмплейте)

Иногда нужно отобразить несколько одинаковых элементов чисто для ui-целей: скелетоны загрузки, звёзды рейтинга, пустые таблицы и т.д., но без реальных данных для итерации.

Вот мой способ (по крайней мере, я нигде такого не видел):

@for (_ of [].constructor(10); track $index) {
<div class="item"></div>
}

Используется Array.constructor, чтобы создать пустую массив фиксированной длины, который @for может перебрать по индексам.

Плюсы ✅

  • Чудо-код (удивит коллег)

  • Минимум кода (не нужно объявлять массив в компоненте)

Минусы ⚠️

  • Чудо-код (может ненадолго ввести в ступор чающего код человека)

Конечно, можно просто использовать Array.from({length: 10})... но так все делают, не интересно)

Норм тема? Как считаете?

Tags:
0
Comments3

Information

Rating
Does not participate
Location
Ташкент, Ташкентская обл., Узбекистан
Registered
Activity

Specialization

Frontend Developer
Lead
Angular
TypeScript
HTML
CSS
JavaScript
Web development