shivtaj virk
shivtaj virk

Reputation: 41

how to access variable of subscribe block of behaviour subject outside the block

I am using behaviour subject and subscribe it in ts file.

trying to access the variable outside the subject block in ts file..

code for service.ts


 private messageSource = new BehaviorSubject<any>(null);

  constructor(
    private apiService: ApiService
  ) {
  }

  // try

  sendMessage(value: any) {
   this.messageSource.next(value);
  }

  get getMessage() {
    return this.messageSource.asObservable();
    
   }```

now in TS file

ngOnInit() {

// this.viewUser = this.commonService.getMessage;

this.subscription = this.commonService.getMessage.subscribe(value => {
  this.viewUser = value; 
  console.log(this.viewUser)
 });


 console.log(this.viewUser)

}

file console showing data.. but in second console , it is showing inital value of behaviour subject ie. null how can i get data outside the block

Upvotes: 0

Views: 953

Answers (4)

Kamran Khatti
Kamran Khatti

Reputation: 4127

The simplest way to share data between sibling components by using TypeScript Setter and Getter instead of an Observable (which we must need to unsubscribe to prevent memory leak).

service.ts

  _message: string;

  set message(value: any) {
    this._message = value;
  }

  get message() {
    return this._message;
  }

Set value from any component or service etc

this.commonService.message = 'some message'; 

And finally get the value without any subscription etc

ngOnInit() {
 this.viewUser = this.commonService.message
 console.log(this.viewUser);
}

Upvotes: 0

ng-hobby
ng-hobby

Reputation: 2199

Observables are new way of handling async requests. Subscriptions to Observables are quite similar to calling a function. But where Observables are different is in their ability to return multiple values called streams.Observables not only able to return a value synchronously, but also asynchronously.

In your case first the second console.log(this.viewUser) is executed which is not initialized with the subscription and because of that you get null first and then your subscription evaluated. You can try this:

app.component.ts

ngOnInit() {
  this.subscription = this.commonService.getMessage.subscribe(value => {
    this.viewUser = value; 
    console.log(this.viewUser)
    this.logViewUser();
  });
}

logViewUser() {
  console.log(this.viewUser)
}

 console.log(this.viewUser)

Upvotes: 0

Barremian
Barremian

Reputation: 31125

Normally I would say there is no way to access an asynchronous variable (this.viewUser here) synchronously.

However since you're using BehaviorSubject, there exists a cheeky way to access it's value synchronously. If you notice, a BehaviorSubject is created with a default value. In other words it always holds some value. RxJS provides a getValue() function (or the value getter - they are synonymous) to synchronously get the value held by the BehaviorSubject. So in your case you could do the following

Service

public messageSource = new BehaviorSubject<any>(null);   // <-- public

constructor(private apiService: ApiService) { }

sendMessage(value: any) {
  this.messageSource.next(value);
}

get getMessage() {
  return this.messageSource.asObservable();
}

Component

ngOnInit() {
  this.viewUser = this.commonService.messageSource.getValue();
  console.log(this.viewUser);
}

There are multiple disadvantages

  1. It's considered an anti-pattern and usually frowned upon since you lose the async behavior.

  2. Say the statement this.viewUser = this.commonService.messageSource.getValue(); is executed before the function sendMessage() in the service, you'd be assigning the value null to the variable this.viewUser. And the variable won't be updated automatically akin to the async behavior with a subscription.

Upvotes: 0

ibenjelloun
ibenjelloun

Reputation: 7733

What's inside your subscribe is running asynchronously.

this.subscription = this.commonService.getMessage.subscribe(value => {
  this.viewUser = value; 
  console.log(this.viewUser)
 });

console.log(this.viewUser) // <-- This is running before what's inside subscribe

You could use the async await to make the function async and whats inside sync :

this.viewUser = await this.commonService.getMessage.asPromise();

The function containing this code should be async.

Upvotes: 0

Related Questions