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

痞子三分冷 提交于 2019-12-17 18:56:02

问题


I found the rxJS docs define them as

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.

and it goes on to give examples but I'm looking for a basic ELI5 explanation. From my understanding is it helps handle and define items in a sequence. Is that correct?

I think it would be most helpful to me and others to see a simple function with and without defining an rxJS Subject to understand why it's important?

Thanks!


回答1:


The easiest way to understand it is to think of a Subject as both a producer and a consumer. It's like an open channel where someone can send a message on one end, and any subscribers will receive it on the other end.

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

In code terms say you have a service with a subject

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

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

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

Note the messages getter returning the Subject as an Observable. This is not required. The Subject is already an observable, and anybody could subscribe directly to the Subject. But I think the asObservable pattern is used as a way to limit what users can do with it, i.e. so users only use it to subscribe to, and not emit to. We save the emitting for the sendMessage method.

Now with this service in place, we can inject it into different components, and this can be a way for two (or more) arbitrary components to communicate (or just receive arbitrary event notifications).

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's own EventEmitter is actually a Subject. When we subscribe to the EventEmitter, we are subscribing to a Subject, and when we emit on the EventEmitter, we are sending a message through the Subject for all subscribers.

See also:

  • Subject vs BehaviorSubject vs ReplaySubject in Angular



回答2:


Subjects are useful when the code you're in is the one that is actually originating the observable data. You can easily let your consumers subscribe to the Subject and then call the next() function to push data into the pipeline.

If, however, you are getting data from other source and are just passing it along (perhaps transforming it first), then you most likely want to use one of the creation operators shown here, such as Rx.Observable.fromEvent like so:

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

This allow you to stay in the functional paradigm, whereas using a Subject, while it has its uses, is considered by some to be a smell that you're trying to force imperative code into a declarative framework.

Here is a great answer that explains the difference in the two paradigms.




回答3:


If you want the most simple explanation ...

Observables are usually the result of something. The result of an http call, and whatever you do with a pipe returns an observable.

But what is the source of those things? Ever wondered how you hook your user events into the whole rxjs thing? The main feature of subjects is that you can call the next() method on them.

When doing reactive programming, the first step is usually to make a list of possible subject you will have.

For instance: lets say we have to make a todo-list app. We will probably have a couple of variables in our component:

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

and in our applicatiuon we will hook these up like this:

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

Using rxjs, we will use operators like merge/combineLatest/withLatestFrom to handle these subjects and define our application logic.

I'll see if I can find the time to make a small example.




回答4:


You can find a study of the semantics of subjects here.

All answered I see are correct. I'll just add that the term subject comes from the observer pattern (cf. https://en.wikipedia.org/wiki/Observer_pattern). As such a subject is sort of a relay, it receives something on one end, and emit it on any of its ends (subscriptions).



来源:https://stackoverflow.com/questions/39885264/what-are-rxjs-subjects-and-the-benifits-of-using-them

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!