В Rx JS каков наилучший способ подписать одноразового прослушивателя на следующее событие, которое соответствует определенному условию? - PullRequest
0 голосов
/ 23 февраля 2020

Может ли какой-нибудь эксперт по Rx JS сказать мне, если мой способ подписки на одноразового слушателя для следующего события, которое удовлетворяет определенному условию, в порядке или есть явно лучший способ? Мне нужен шаблон, который я могу применить к любому типу событий, и я хочу, чтобы тип моего события выводился в конце.

import { Subject } from "rxjs";
import { first, map } from "rxjs/operators"

//I have this subject...
const subject = new Subject<{
    eventName: "TEXT";
    text: string;
} | {
    eventName: "AGE";
    age: number;
}>();

//... An I want to subscribe this callback for the next text event..
const next= (text: string) => console.log(text);

//...Is this the best type-safe way to do it? 
subject
  .pipe(map(data => data.eventName === "TEXT" ? [data.text] : null))
  .pipe(first((data): data is NonNullable<typeof data> => !!data))
  .subscribe(([text])=>next(text))
  ;

subject.next({
  "eventName": "TEXT",
  "text": "Hello World"
});

запустите код

Спасибо за помощь.

1 Ответ

1 голос
/ 23 февраля 2020

Я бы использовал оператор filter перед оператором first. Кроме того, если вам нужны некоторые проверки типов, вы также можете добавить некоторые определения типов для событий, которые будут отправлены субъектом.

Учтите также, что с помощью first вы завершите подписку на поток после отправки первого события типа TEXT любое последующее событие будет проигнорировано этой подпиской.

Это код, который вы можете использовать

type TextEvent = {
    eventName: "TEXT";
    text: string;
};
type AgeEvent = {
    eventName: "AGE";
    age: number;
};

//I have this subject...
const subject = new Subject<TextEvent | AgeEvent>();

//... An I want to subscribe this callback for the next text event..
const next= (text: string) => console.log(text);

//...Is this the best type safe way to do it ? 
subject
  .pipe(
    filter(event => event.eventName === 'TEXT'),
    first()
  )
  .subscribe( {
    next: (event: TextEvent ) => console.log(event.text),
    complete: () => console.log('DONE')
  }
  );

// this is not going to be printed
subject.next({
  eventName: "AGE",
  age: 99
});
// this IS going to be printed
subject.next({
  eventName: "TEXT",
  text: "Hello World - I will be printed since I am the first TEXT event to be emitted"
});
// this IS NOT going to be printed
subject.next({
  eventName: "TEXT",
  text: "I WILL NOT BE PRINTED since I come after the first TEXT event emitted"
});
...