admin管理员组

文章数量:1426512

Within my anguular app , i ve this service :

@Injectable()
export class myService{

  myBehaviouSubject= new BehaviorSubject("");


  setData(){
     this.myBehaviouSubject.next("123");
  }

}

Inside my appponent , i m able to get the value , but i want to keep it readonly or editable only inside the service itself , i want to prevent to push any data from ponent (.next('DATA'))

    @Component({

    })
    export class AppComponent implements OnInit {

      constructor(public myService : MyService) { }

    getData(){
      // GET VALUE
      this.myService.myBehaviouSubject.value
    }

    unwantedMethodToSetValue(){
           // SET VALUE -> i want to prevent this
           this.myService.myBehaviouSubject.next("unwanted value")

    }

}

Suggestions ?

Within my anguular app , i ve this service :

@Injectable()
export class myService{

  myBehaviouSubject= new BehaviorSubject("");


  setData(){
     this.myBehaviouSubject.next("123");
  }

}

Inside my app.ponent , i m able to get the value , but i want to keep it readonly or editable only inside the service itself , i want to prevent to push any data from ponent (.next('DATA'))

    @Component({

    })
    export class AppComponent implements OnInit {

      constructor(public myService : MyService) { }

    getData(){
      // GET VALUE
      this.myService.myBehaviouSubject.value
    }

    unwantedMethodToSetValue(){
           // SET VALUE -> i want to prevent this
           this.myService.myBehaviouSubject.next("unwanted value")

    }

}

Suggestions ?

Share Improve this question asked Feb 20, 2020 at 17:58 firasKoubaafirasKoubaa 6,88530 gold badges87 silver badges164 bronze badges 1
  • what's your use case to protect the .next()? Could you please provide your reason why this might be useful? – HoseinGhanbari Commented Feb 20, 2020 at 18:06
Add a ment  | 

4 Answers 4

Reset to default 4

You can keep the observable inside service only by declaring it as private field of a class.

@Injectable()
export class myService {

  private myBehaviouSubject = new BehaviorSubject("");

  // Use this observable inside the app ponent class.
  myBehaviouSubjectObservable = myBehaviouSubject.asObservable();

  setData() {
    this.myBehaviouSubject.next("123");
  }
}

@Component({

})
export class AppComponent implements OnInit {

  constructor(public myService: MyService) {}

  getData() {
    // You can subscribe to observable and can get value here
    this.myService.myBehaviouSubjectObservable.subscribe((value) => {
      console.log(value);
    })
  }

  unwantedMethodToSetValue() {
    // SET VALUE -> you cannot do this here now.
    this.myService.myBehaviouSubject.next("unwanted value")

  }

}

Use property access modifiers:

@Injectable()
export class MyService{
  private myValueSubject: BehaviorSubject<string> = new BehaviorSubject<string>("");
  public readonly myValueObservable: Observable<string> = this.myValueSubject.asObservable();

  public setData() {
     this.myValueSubject.next("123");
  }
  public getData(): string {
    return this.myValueSubject.value;
  }
}

Instances of MyService will not have a publicly accessible subject.

I usually try to avoid a method like getData, favoring subscriptions to the related observable. If I ever find myself writing those kinds of methods, it's a warning flag to re-evaluate my architecture. If you just want to store a value and get/set it with methods, use a plain old private property. The entire purpose of the subject is defeated if you are only ever getting the value through a method like getData()

Check out the documentation for typescript classes, which discusses access modifiers: https://www.typescriptlang/docs/handbook/classes.html

The traditional answer : If you return the Subject as an observable, you disallow .next() calls.

But in your case, you also want direct access to the current value without subscribing, so you could add a getter for that too.

@Injectable()
export class myService{

  private readonly myBehaviouSubject = new BehaviorSubject("");


  setData(){
     this.myBehaviouSubject.next("123");
  }
  public get myObservable$(): Observable<string>{
    return this.myBehaviourSubject;
  }
  public get currentValue(): string{
    return this.myBehaviourSubject.value;
  }

}

https://stackblitz./edit/angular-protected-rxjs-subject

in this solution which I hope meet you needs:

  • be aware that there is no subscription
  • fetching updates handled manually
  • Property 'myBehaviourSubject' is private and only accessible
    within class 'TestService'.

本文标签: javascriptRxjsprevent pushing data to subjects from outisde the serviceStack Overflow