BehaviorSubject vs Observable?

前端 未结 10 2264
迷失自我
迷失自我 2020-11-22 02:17

I\'m looking into Angular RxJs patterns and I don\'t understand the difference between a BehaviorSubject and an Observable.

From my underst

相关标签:
10条回答
  • 2020-11-22 03:10

    One thing I don't see in examples is that when you cast BehaviorSubject to Observable via asObservable, it inherits behaviour of returning last value on subscription.

    It's the tricky bit, as often libraries will expose fields as observable (i.e. params in ActivatedRoute in Angular2), but may use Subject or BehaviorSubject behind the scenes. What they use would affect behaviour of subscribing.

    See here http://jsbin.com/ziquxapubo/edit?html,js,console

    let A = new Rx.Subject();
    let B = new Rx.BehaviorSubject(0);
    
    A.next(1);
    B.next(1);
    
    A.asObservable().subscribe(n => console.log('A', n));
    B.asObservable().subscribe(n => console.log('B', n));
    
    A.next(2);
    B.next(2);
    
    0 讨论(0)
  • 2020-11-22 03:18

    BehaviorSubject vs Observable : RxJS has observers and observables, Rxjs offers a multiple classes to use with data streams, and one of them is a BehaviorSubject.

    Observables : Observables are lazy collections of multiple values over time.

    BehaviorSubject:A Subject that requires an initial value and emits its current value to new subscribers.

     // RxJS v6+
    import { BehaviorSubject } from 'rxjs';
    
    const subject = new BehaviorSubject(123);
    
    //two new subscribers will get initial value => output: 123, 123
    subject.subscribe(console.log);
    subject.subscribe(console.log);
    
    //two subscribers will get new value => output: 456, 456
    subject.next(456);
    
    //new subscriber will get latest value (456) => output: 456
    subject.subscribe(console.log);
    
    //all three subscribers will get new value => output: 789, 789, 789
    subject.next(789);
    
    // output: 123, 123, 456, 456, 456, 789, 789, 789
    
    0 讨论(0)
  • 2020-11-22 03:19

    The Observable object represents a push based collection.

    The Observer and Observable interfaces provide a generalized mechanism for push-based notification, also known as the observer design pattern. The Observable object represents the object that sends notifications (the provider); the Observer object represents the class that receives them (the observer).

    The Subject class inherits both Observable and Observer, in the sense that it is both an observer and an observable. You can use a subject to subscribe all the observers, and then subscribe the subject to a backend data source

    var subject = new Rx.Subject();
    
    var subscription = subject.subscribe(
        function (x) { console.log('onNext: ' + x); },
        function (e) { console.log('onError: ' + e.message); },
        function () { console.log('onCompleted'); });
    
    subject.onNext(1);
    // => onNext: 1
    
    subject.onNext(2);
    // => onNext: 2
    
    subject.onCompleted();
    // => onCompleted
    
    subscription.dispose();
    

    More on https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md

    0 讨论(0)
  • 2020-11-22 03:20

    An observable allows you to subscribe only whereas a subject allows you to both publish and subscribe.

    So a subject allows your services to be used as both a publisher and a subscriber.

    As of now, I'm not so good at Observable so I'll share only an example of Subject.

    Let's understand better with an Angular CLI example. Run the below commands:

    npm install -g @angular/cli
    
    ng new angular2-subject
    
    cd angular2-subject
    
    ng serve
    

    Replace the content of app.component.html with:

    <div *ngIf="message">
      {{message}}
    </div>
    
    <app-home>
    </app-home>
    

    Run the command ng g c components/home to generate the home component. Replace the content of home.component.html with:

    <input type="text" placeholder="Enter message" #message>
    <button type="button" (click)="setMessage(message)" >Send message</button>
    

    #message is the local variable here. Add a property message: string; to the app.component.ts's class.

    Run this command ng g s service/message. This will generate a service at src\app\service\message.service.ts. Provide this service to the app.

    Import Subject into MessageService. Add a subject too. The final code shall look like this:

    import { Injectable } from '@angular/core';
    import { Subject } from 'rxjs/Subject';
    
    @Injectable()
    export class MessageService {
    
      public message = new Subject<string>();
    
      setMessage(value: string) {
        this.message.next(value); //it is publishing this value to all the subscribers that have already subscribed to this message
      }
    }
    

    Now, inject this service in home.component.ts and pass an instance of it to the constructor. Do this for app.component.ts too. Use this service instance for passing the value of #message to the service function setMessage:

    import { Component } from '@angular/core';
    import { MessageService } from '../../service/message.service';
    
    @Component({
      selector: 'app-home',
      templateUrl: './home.component.html',
      styleUrls: ['./home.component.css']
    })
    export class HomeComponent {
    
      constructor(public messageService:MessageService) { }
    
      setMessage(event) {
        console.log(event.value);
        this.messageService.setMessage(event.value);
      }
    }
    

    Inside app.component.ts, subscribe and unsubscribe (to prevent memory leaks) to the Subject:

    import { Component, OnDestroy } from '@angular/core';
    import { MessageService } from './service/message.service';
    import { Subscription } from 'rxjs/Subscription';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html'
    })
    export class AppComponent {
    
      message: string;
      subscription: Subscription;
    
      constructor(public messageService: MessageService) { }
    
      ngOnInit() {
        this.subscription = this.messageService.message.subscribe(
          (message) => {
            this.message = message;
          }
        );
      }
    
      ngOnDestroy() {
        this.subscription.unsubscribe();
      }
    }
    

    That's it.

    Now, any value entered inside #message of home.component.html shall be printed to {{message}} inside app.component.html

    0 讨论(0)
提交回复
热议问题