Angular 2 RxJS проверяет, активно ли событие мыши после задержки

Я использую Angular 2 для создания директивы. У меня есть следующие события, связанные с хост-компонентом:

host: {
    '(mouseenter)': 'onMouseEnter($event)',
    '(mouseleave)': 'onMouseLeave($event)'
}

Я также создал два потока и слушателя в директиве для управления двумя событиями.

export class PopupDirective {
    private _mouseEnterStream: EventEmitter<any> = new EventEmitter();
    private _mouseLeaveStream: EventEmitter<any> = new EventEmitter();

    onMouseEnter($event) {
         this._mouseEnterStream.emit($event);
    }

    onMouseLeave($event) {
         this._mouseLeaveStream.emit($event);
    }
}

Я хочу, чтобы мой subscribe вызывался только в том случае, если событие mouseenter все еще активно после фиксированной задержки (т. Е. mouseleave не произошло). Я пытался сделать это таким образом, но он не работает (что имеет смысл, я просто не знаю, как это исправить).

this._mouseEnterStream.flatMap((e) => {
  return Observable
    .of(e)
    .takeUntil(this._mouseLeaveStream);
}).delay(2000).subscribe(
  () => console.log('yay, it worked!')
);

Кто-нибудь с опытом работы с Angular 2/RxJS знает, как мне к этому подойти?


person Jack Guy    schedule 10.02.2016    source источник
comment
Откуда this._mouseStream?   -  person Günter Zöchbauer    schedule 10.02.2016
comment
@GünterZöchbauer Извините, это должен быть mouseEnterStream   -  person Jack Guy    schedule 10.02.2016
comment
Кстати, поскольку вы используете Rx, вам действительно не нужны EventEmitters. Просто используйте Темы вместо этого. Немного удивлен, что вы можете использовать EventEmitters как Observables, возможно, ng2 преобразует их под капотом.   -  person kakigoori    schedule 10.02.2016
comment
@kakigoori Разве не все дело в том, что EventEmitters являются наблюдаемыми? Спасибо за подсказку.   -  person Jack Guy    schedule 10.02.2016
comment
обычно, чтобы использовать EventEmitters для Observables в других проектах, вы должны использовать статический метод fromEvent для создания наблюдаемого из генератора событий. Раньше я активно использовал эмиттеры событий, но холодные/горячие потоки, операторы и все создание/подписка/удаление слишком хороши. (вы можете найти сообщение Андре здесь полезным: программирование rxjs против eventemitter в узле js"> stackoverflow.com/questions/25338930/)   -  person kakigoori    schedule 10.02.2016
comment
@kakigoori Это было полезно, спасибо. Похоже, что EventEmitter ng2 может быть неправильным. Глядя на документы кажется, что EventEmitter намеренно основан на Наблюдателе.   -  person Jack Guy    schedule 10.02.2016


Ответы (2)


Ответ Гюнтера - это именно то, что вы ожидаете, но вы должны использовать оператор of вместо оператора return, которого не существует.

this._mouseEnterStream.flatMap((e) => {
  console.log('_mouseEnterStream.flatMap');
  return Observable
      .of(e)
      .delay(2000)
      .takeUntil(this._mouseLeaveStream);
}).subscribe(
  (e) => {
    console.log('yay, it worked!');
    console.log(e);
  }
);

См. соответствующий plunkr: https://plnkr.co/edit/vP3xRDXxFanqzLEKd3eo?p=preview.

Кроме того, существует предложение в Angular, которое направлено на упрощение способа создания наблюдаемых из События DOM с использованием Rx через синтаксис шаблона.

person Thierry Templier    schedule 10.02.2016
comment
Если вы хотите вернуть только одно значение, .just имеет больше смысла. Но для пользователей, не владеющих языком Haskelly, это может показаться тарабарщиной. - person kakigoori; 10.02.2016
comment
Спасибо за ваш комментарий, но этот оператор не существует в Rxjs 5.0.0-beta.0. Смотрите эту ошибку: Rx_1.Observable.just is not a function - person Thierry Templier; 10.02.2016
comment
О, извините, похоже, это указано в документах по миграции для бета-версии RxJS5. Хотя как-то грустно. - person kakigoori; 10.02.2016
comment
Не знаю, почему .subscribe нужно было подключить к .flatMap, чтобы это работало, но это идеально! Спасибо. - person Jack Guy; 10.02.2016
comment
Это просто для создания потока данных. Когда первое событие будет получено, оно будет сопоставлено с другой цепочкой, которая обрабатывает задержку... - person Thierry Templier; 10.02.2016

Выглядит очень похоже на Как установить тайм-аут события в RxJS?

this.myStream = this._mouseEnterStream
    .flatMap((e) => {
        return Observable
            .of(e)
            .delay(2000)
            .takeUntil(mouseLeaveStream);
    });

myStream.subscribe((x) => { 
        console.log('onNext: ', x);
});

Я сам не использую TS или Rx (только Dart), поэтому я не знаю, правильный ли это синтаксис или совпадают ли имена операторов с теми, которые доступны для Angular.

person Günter Zöchbauer    schedule 10.02.2016
comment
Интересно, что я попробовал эту опцию непосредственно перед тем, как сделать этот пост, но по какой-то причине .susbcribe должен быть подключен к .flatMap, чтобы он работал, иначе next срабатывает сразу при событии mouseenter. - person Jack Guy; 10.02.2016