RxJS, почему fromEvent () регистрирует новое событие для каждой подписки? - PullRequest
2 голосов
/ 30 марта 2019

Допустим, у нас есть следующий код

const clickEvent$ = fromEvent(document, 'click').pipe(
    pluck('target')
);

clickEvent$.pipe(
    filter(node => node.id === 'button1')
).subscribe(() => {
    console.log('Button 1 clicked!');
});

clickEvent$.pipe(
    filter(node => node.id === 'button2')
).subscribe(() => {
    console.log('Button 2 clicked!');
});

Когда я смотрю на зарегистрированные события в отладчике, я вижу, что в документе зарегистрировано два события щелчка.При увеличении количества подписок до clickEvent$ число событий, зарегистрированных в документе, также увеличивается с каждой подпиской.

снимок экрана отладчика

В сравнении только нижеприведенный кодрегистрирует одно событие независимо от того, сколько дел я добавляю в оператор switch.

document.addEventListener('click', (event) => {
    switch (event.target.id) {
        case 'Button1':
            console.log('Button 1 clicked!');
            break;
        case 'Button2':
            console.log('Button 2 clicked!');
            break;
    }
});

Поэтому мой вопрос: -

  • Почему каждая подписка на clickEvent $ (или любуюDOM Event Stream) добавляет новое событие в документ.
  • Как это влияет на производительность при наличии 100 или более подписок
  • Есть ли способ обойти это, чтобы в документ добавлялся только один прослушиватель событий.

Вот что я знаю о наблюдаемых горячих и холодных

  • Все наблюдаемые последовательности, созданные из событий DOM, являются горячими и используются по умолчанию.
  • В случаеГорячая наблюдаемая, подписчики начинают получать события только с момента подписки.Принимая во внимание, что в случае холодной наблюдаемой подписчики получают все события, которые может произвести наблюдаемая. Оператор
  • share() может использоваться, чтобы сделать холодную наблюдаемую горячей.

Спасибо!

1 Ответ

2 голосов
/ 30 марта 2019

, как вы можете видеть, нажав run code snippet, ответ - да , слушатели присоединяются каждый раз, когда вы subscribe подключаетесь к потоку click$.

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

const { fromEvent } = rxjs;
const { mapTo } = rxjs.operators;

const target = document.getElementById('test');
/* ignore, debug */
const $delegate = target.addEventListener;

target.addEventListener = (...args) => {
  console.log('registering listener');
  
  return $delegate.apply(target, args);
};
/* // */

const click$ = fromEvent(target, 'click');

click$.pipe(
    mapTo('stream 1: click'),
).subscribe(console.log);

click$.pipe(
    mapTo('stream 2: click'),
).subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.js"></script>

<button id="test">click here</button>

Вы можете создать shared потоков, чтобы избежать этого.

const { fromEvent } = rxjs;
const { mapTo, share } = rxjs.operators;

const target = document.getElementById('test');
/* ignore, debug */
const $delegate = target.addEventListener;

target.addEventListener = (...args) => {
  console.log('registering listener');
  
  return $delegate.apply(target, args);
};
/* // */

const click$ = fromEvent(target, 'click').pipe(
  share(), // <= share operator
);

click$.pipe(
    mapTo('stream 1: click'),
).subscribe(console.log);

click$.pipe(
    mapTo('stream 2: click'),
).subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.js"></script>

<button id="test">click here</button>

Как вы можете видеть в последнем примере, журнал registering listener происходит только один раз. Дополнительная информация о the share operator

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...