请选择 进入手机版 | 继续访问电脑版

RxJS:主题,行为主题和重播主题

前端开发  / TypeScript  / 倒序浏览   © 著作权归作者本人所有

#楼主# 2020-4-12

跳转到指定楼层

Rx中的主题是一种特殊的混合体,可以同时充当可观察者和观察者。这样,可以将数据推送到主题中,主题的订户将依次接收该推送的数据。

主题对于多播或数据源不容易转换为可观察对象时很有用。如这篇出色的文章所述,很容易过度使用主题,并且常常可以避免主题的产生,否则可以创建可观察的源。

除了香草主题外,还有一些特殊类型的主题,例如异步主题行为主题重播主题。在本文中,我们将介绍主题行为主题重播主题

创建主题就像新建一个RxJS的Subject实例一样简单:

const mySubject = new Rx.Subject();

可以创建多个订阅,并且在内部该主题将保留一个订阅列表:

const mySub = mySubject.subscribe(x => console.log(`${x} ${x}`));
const mySub2 = mySubject.subscribe(x => console.log(x.toUpperCase()));

可以使用一种方法将数据推入主题:

mySubject.next(' Hello!');

//  Hello!  Hello!
//  HELLO!

将数据推送到主题中时,它将遍历其内部订阅列表,然后将数据放入每个订阅中。

简单的例子

这是一个示例,演示如何将数据获取到订阅中:

const mySubject = new Rx.Subject();

mySubject.next(1);

const subscription1 = mySubject.subscribe(x => {
  console.log('From subscription 1:', x);
});

mySubject.next(2);

const subscription2 = mySubject.subscribe(x => {
  console.log('From subscription 2:', x);
});

mySubject.next(3);

subscription1.unsubscribe();

mySubject.next(4);

在此示例中,这是将在控制台中打印的结果:

From subscription 1: 2
From subscription 1: 3
From subscription 2: 3
From subscription 2: 4

请注意,迟到的订阅是如何在推送到主题中的某些数据上丢失的。我们将在下面看到如何通过“ 行为主题”或“ 重播主题 ”来管理该主题

错误与完成

当主题完成或出错时,所有内部订阅也会完成或出错:

const mySubject = new Rx.Subject();

const sub1 = mySubject.subscribe(null, err =>
  console.log('From sub1:', err.message)
);

const sub2 = mySubject.subscribe(null, err =>
  console.log('From sub2:', err.message)
);

mySubject.error(new Error('Oh nooo!'));

// From sub1: Oh nooo!
// From sub2: Oh nooo!

多播

主体的真正力量在于多播,其中,主体作为观察者传递给可观察对象,这意味着,当可观察对象发出时,数据将被多播给所有主体的订阅:

这里就是一个例子trickleWords每750毫秒观察到发出一个字。

const mySubject = new Rx.Subject();
const words = ['Hot Dog', 'Pizza', 'Hamburger'];

const trickleWords = Rx.Observable.zip(
  Rx.Observable.from(words),
  Rx.Observable.interval(750),
  word => word
);

const subscription1 = mySubject.subscribe(x => {
  console.log(x.toUpperCase());
});

const subscription2 = mySubject.subscribe(x => {
  console.log(
    x
      .toLowerCase()
      .split('')
      .reverse()
      .join('')
  );
});

trickleWords.subscribe(mySubject);

这是所有值发出后的打印结果:

HOT DOG
god toh
PIZZA
azzip
HAMBURGER
regrubmah

可观察的

所述asObservable运算符可用于给受试者转化为可观察到的。当您想要公开主题中的数据但同时防止将数据无意中推入主题中时,这可能很有用:

const mySubject = new Rx.Subject();
const myObs = mySubject.asObservable();

mySubject.next('Hello');
myObs.next('World!'); // TypeError: myObs.next is not a function

重播主题

如您先前所见,主题订阅过后将错过先前发出的数据。重播主题可以通过保留将要发送给新订阅的先前值的缓冲区来帮助解决此问题。

这是重放主题的用法示例,其中保留了两个先前值的缓冲区并在新订阅中发出:

const mySubject = new Rx.ReplaySubject(2);

mySubject.next(1);
mySubject.next(2);
mySubject.next(3);
mySubject.next(4);

mySubject.subscribe(x => {
  console.log('From 1st sub:', x);
});

mySubject.next(5);

mySubject.subscribe(x => {
  console.log('From 2nd sub:', x);
});

这就是为我们提供控制台的功能:

From 1st sub: 3
From 1st sub: 4
From 1st sub: 5
From 2nd sub: 4
From 2nd sub: 5

行为主体

行为主题类似于重播主题,但是将仅重新发射最后一个发出的值,或者如果先前没有发出任何值,则默认为默认值:

const mySubject = new Rx.BehaviorSubject('Hey now!');

mySubject.subscribe(x => {
  console.log('From 1st sub:', x);
});

mySubject.next(5);

mySubject.subscribe(x => {
  console.log('From 2nd sub:', x);
});

结果:

From 1st sub: Hey now!
From 1st sub: 5
From 2nd sub: 5
转播转播
回复

使用道具

245

主题

248

帖子

857

积分

网站编辑

Rank: 8Rank: 8

积分
857
qqpite 发表于 2020-4-18 15:22:11

很好

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于作者

qqpite

网站编辑

  • 主题

    245

  • 帖子

    248

  • 关注者

    0

手机版|ObjectX 超对象 |粤ICP备20005929号
Powered by  © 2019-2020版权归ObjectX 超对象