Angular Reactive и общение через сервисы

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

Есть ли обратная сторона отказа от использования RxJS или Signals в этом случае? Я понимаю, что использование RxJS или Signals — это своего рода предписанный способ делать что-то в Angular, и это веская причина для этого, но мне интересно, есть ли реальная причина помимо этого. Может ли это вызвать какие-либо проблемы или ошибки?

Пример сервиса ниже и вот образец Stackblitz.

Услуга:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class MyService {
  private counter: number = 0;

  increment() {
    this.counter += 1;
  }

  getValue() {
    return this.counter;
  }
}

Компонент1:

import { Component } from '@angular/core';
import { MyService } from './MyService';

@Component({
  selector: 'component1',
  standalone: true,
  template: `
    <h1>Component 1</h1>
    Current Value: {{ valueFromService }}
    <button (click) = "increment()">Click to increment</button>
  `,
})
export class Component1 {
  constructor(private myService: MyService) {}

  get valueFromService() {
    return this.myService.getValue();
  }

  increment() {
    this.myService.increment();
  }
}

Компонент 2:

import { Component } from '@angular/core';
import { MyService } from './MyService';

@Component({
  selector: 'component2',
  standalone: true,
  template: `
    <h1>Component 2</h1>
    Current Value: {{ valueFromService }}
  `,
})
export class Component2 {
  constructor(private myService: MyService) {}

  get valueFromService() {
    return this.myService.getValue();
  }
}
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
0
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Использование Observables хорошо сочетается с OnPush ChangeDetectionStrategy, которая обычно положительно влияет на производительность во время выполнения. Это также упрощает работу с производными состояниями, обработку нескольких одновременных обновлений и запуск побочных эффектов в качестве реакции на обновления состояния.

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

  1. Запускается событие «щелчок»
  2. Задача для связанного обработчика событий добавляется в цикл событий.
  3. Когда браузер решает, что пришло время запустить что-то из цикла событий, он запускает обработчик, который меняет состояние службы.
  4. Zone.js (библиотека, которую Angular использует внутри себя для отслеживания непрозрачного состояния цикла событий) уведомляет Angular о том, что очередь цикла событий пуста, и Angular запускает обнаружение изменений.
  5. Во время цикла обнаружения изменений Angular повторно отображает компоненты, и именно тогда компонент извлекает новое значение из службы.

Таким образом, обновление значения услуги и обновление отображаемого значения как бы разделены. Если значение обновляется в результате чего-то, что Zone.js не может перехватить (например, awync/await), представление не отразит изменения. Стоит отметить, что события могут происходить довольно часто, и проверка каждого компонента по каждому событию может стать довольно сложной задачей. Вот почему рекомендуется использовать OnPush ChangeDetectionStrategy.

Не вдаваясь в подробности, при использовании OnPush Angular пропускает проверку этого компонента и всех его дочерних элементов, если только некоторые входные данные не изменены или компонент не помечен для проверки, например, звоню ChangeDetectorRef.markForCheck(). Это обычная схема получения наблюдаемого из сервиса и привязки к нему в шаблоне через канал async, и канал вызывает markForCheck каждый раз, когда Observable излучает значение. Таким образом, хотя цикл обнаружения изменений все еще необходимо запустить, обновление наблюдаемого значения делает компонент проверенным, а те компоненты, которые не имеют изменений, не будут проверяться вообще.

Вот демо

Что касается производных состояний и побочных эффектов, давайте представим, что у нас есть два сервиса A и B, и когда значение обновляется в A, нужно что-то сделать в B. Без Observables, которые потребовали бы внедрения B в A, и что, если у нас есть десятки таких соединений ? Довольно быстро становится грязно. То же самое справедливо и для компонентов: довольно распространенная ситуация, когда перед рендерингом значения его необходимо преобразовать, объединить с другим и только потом визуализировать. Хотя это можно сделать внутри геттера, запускать их в каждом цикле CD — пустая трата ресурсов.

И последнее: некоторые API Angular представлены в виде Observable, например, реактивные формы, события маршрутизатора, HttpClient, поэтому их проще встроить в свои собственные вещи, если они также основаны на Observable.

Спасибо за подробное объяснение. Другая причина, которую упомянул коллега, заключается в том, что команда Angular надеется в какой-то момент устранить Zone.js, и использование реактивных библиотек (RxJS, Signals), вероятно, поможет в будущем защититься от этого.

Jim Cooper 18.03.2024 17:43

Другие вопросы по теме