关于javascript:什么是RxJS主题以及使用它们的好处?

What are RxJS Subject's and the benifits of using them?

我发现RXJS文档将它们定义为

What is a Subject? An RxJS Subject is a special type of Observable that allows values to be multicasted to many Observers. While plain Observables are unicast (each subscribed Observer owns an independent execution of the Observable), Subjects are multicast.

它继续给出例子,但我在寻找一个基本的eli5解释。据我所知,它有助于按顺序处理和定义项目。对吗?

我认为看到一个简单的函数,不管是否定义了一个RXJS主题,理解它为什么重要,对我和其他人来说都是最有帮助的。

谢谢!


要理解它,最简单的方法是把Subject看作生产者和消费者。这就像一个开放的频道,有人可以在一端发送消息,任何订户都可以在另一端接收。

1
2
3
4
5
6
7
                                  +---------------
Sender                            | =>  =>  =>  =>  Subscriber
           -----------------------+   +-----------
Message =>  =>  =>  =>  =>  =>  =>  =>  =>  =>  =>  Subscriber
           -----------------------+   +-----------
                                  | =>  =>  =>  =>  Subscriber
                                  +---------------

用代码术语来说,你有一个主题服务

1
2
3
4
5
6
7
8
9
10
11
class MessageService {
  private _messages = new Subject<Message>();

  get messages: Observable<Message> {
    return this._messages.asObservable();
  }

  sendMessage(message: Message) {
    this._messages.next(message);
  }
}

请注意,messagesgetter将主题作为可观察的返回。这不是必需的。Subject已经是可观测的,任何人都可以直接订阅Subject。但是我认为asObservable模式是用来限制用户可以使用它做什么的一种方式,也就是说,用户只使用它来订阅,而不发射到。我们为sendMessage方法节省了发射。

现在有了这个服务,我们可以将它注入到不同的组件中,这可以是两个(或更多)任意组件进行通信(或只是接收任意事件通知)的一种方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class ComponentOne {
  constructor(private messages: MessageService) {}

  onClick() {
    this.messages.sendMessage(new Message(..));
  }
}

class ComponentTwo {
  constructor(private messages: MessageService) {}

  ngOnInit() {
    this.messages.messages.subscribe((message: Message) => {
      this.message = message;
    });
  }
}

Angular自己的EventEmitter实际上是一个Subject。当我们订阅EventEmitter时,我们订阅Subject,当我们在EventEmitter上订阅emit时,我们通过Subject向所有订户发送消息。

参见:

  • 受试者vs行为受试者vs替换受试者角度

当你所使用的代码实际上是源于可观测数据的代码时,主题是有用的。您可以方便地让您的消费者订阅Subject,然后调用next()函数将数据推送到管道中。

但是,如果您从其他源获取数据,并且只是在传递数据(可能首先转换数据),那么您很可能希望使用此处显示的创建操作符之一,例如Rx.Observable.fromEvent,如:

1
2
var clicks = Rx.Observable.fromEvent(document, 'click');
clicks.subscribe(x => console.log(x));

这允许您停留在功能范式中,而使用Subject虽然有其用途,但有些人认为它是一种气味,即您试图将命令式代码强制到声明性框架中。

这是一个很好的答案,可以解释这两个范例之间的差异。


您可以在这里找到主题语义的研究。

我看到的回答都是正确的。我要补充的是,术语Subject来自观察者模式(参见https://en.wikipedia.org/wiki/observer_pattern)。由于这样的主题是一种中继,它在一端接收某个内容,并在其任何一端(订阅)发出该内容。


如果你想要最简单的解释…

可见光通常是某种东西的结果。HTTP调用的结果以及对管道所做的任何操作都会返回一个可观察的。

但是这些东西的来源是什么呢?有没有想过如何将用户事件与整个RXJS关联起来?主题的主要特性是您可以对其执行所有的next()方法。

在进行反应式编程时,第一步通常是列出可能的主题。

例如:假设我们必须制作一个待办事项列表应用程序。我们的组件中可能有几个变量:

1
2
3
public deleteItem$ = Subject<TodoItem> = new Subject();
public addItem$ = Subject<TodoItem> = new Subject();
public saveList$ = Subject<TodoItem[]> = new Subject();

在我们的应用中,我们会像这样连接:

1
<button (click)="deleteItem$.next(item)">Delete</button>

使用RXJS,我们将使用诸如merge/combinelatest/withlatestfrom之类的操作符来处理这些主题并定义我们的应用程序逻辑。

我看看是否有时间做个小例子。