什么是RxJS主题和使用它们的好处?

时间:2016-10-05 23:33:01

标签: javascript angular typescript rxjs subject

我发现rxJS docs将它们定义为

  

什么是主题? RxJS主题是一种特殊类型的Observable,允许将值多播到许多观察者。虽然普通的Observable是单播的(每个订阅的Observer都拥有Observable的独立执行),但是Subjects是多播的。

它继续举例,但我正在寻找一个基本的ELI5解释。根据我的理解,它有助于处理和定义序列中的项目。那是对的吗?

对于我和其他人来说,看看一个简单的函数,有没有定义 rxJS主题来理解为什么它很重要对我有帮助?

谢谢!

4 个答案:

答案 0 :(得分:18)

理解它的最简单方法是将Subject视为制作者使用者。这就像一个开放的频道,有人可以在一端发送消息,任何订阅者都会在另一端接收消息。

                                  +---------------
Sender                            | =>  =>  =>  =>  Subscriber
           -----------------------+   +----------- 
Message =>  =>  =>  =>  =>  =>  =>  =>  =>  =>  =>  Subscriber
           -----------------------+   +-----------
                                  | =>  =>  =>  =>  Subscriber
                                  +---------------

在代码术语中说您有一个主题服务

class MessageService {
  private _messages = new Subject<Message>();

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

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

注意messages getter将Subject作为Observable返回。这不是必需Subject已经是一个可观察的,任何人都可以直接订阅Subject。但我认为asObservable模式用作限制用户可以使用它的方式,即用户只使用它来订阅,而不是发出到。我们保存sendMessage方法的发射。

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

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,当我们emit上的EventEmitter时,我们会通过Subject发送消息适用于所有订阅者。

另见:

答案 1 :(得分:7)

当您所在的代码是实际发起可观察数据的代码时,主题非常有用。您可以轻松地让您的消费者订阅Subject,然后调用next()函数将数据推送到管道中。

但是,如果您从其他来源获取数据并且只是将其传递(可能首先将其转换),那么您很可能希望使用here所示的创建运算符之一,例如{{ 1}} like so

Rx.Observable.fromEvent

这允许你保留在功能范例中,而使用var clicks = Rx.Observable.fromEvent(document, 'click'); clicks.subscribe(x => console.log(x)); 虽然它有其用途,但有些人认为这是一种气味,你试图强制命令性代码进入声明性框架。

Here是一个很好的答案,可以解释两种范式的不同之处。

答案 2 :(得分:1)

你可以找到一个关于主题here的语义的研究。

我看到的所有答案都是正确的。我只想补充说术语subject来自观察者模式(参见https://en.wikipedia.org/wiki/Observer_pattern)。因为这样的主题是一种中继,它在一端接收某些东西,并在其任何一端(订阅)发出它。

答案 3 :(得分:1)

如果您想要最简单的说明...

可观察物通常是某物的结果。 http调用的结果以及使用管道进行的任何操作都将返回可观察到的结果。

但是这些东西的来源是什么?是否曾经想过如何将用户事件与整个rxjs挂钩?主题的主要特征是您可以在主题上调用next()方法。

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

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

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

在我们的应用程序中,我们将像这样将它们连接起来:

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

使用rxjs,我们将使用merge / combineLatest / withLatestFrom之类的运算符来处理这些主题并定义我们的应用程序逻辑。

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