Reputation:
How do I get the last value from an Observable in Angular 8?
let test = new BehaviorSubject<any>('');
test.next(this.AddressObservable);
let lastValue = test.subscribe(data=>console.log(data.value));
For some reason it is not working, checking debugger.
However, this is working in html, AddressObservable | async
Trying to utilize this link, want to store value in variable or display in console log. Any newer syntax would be helpful .
How to get last value when subscribing to an Observable?
Note:
AddressObservable
is of type: Observable<AddressDto>
Upvotes: 5
Views: 23733
Reputation: 13515
Judging by the question, there seems to be confusion with the BehaviorSubject
and what it does.
A Subject
is effectively a stream of values from some source that you can subscribe to. Whenever a new value is emitted, it arrives in the subscribe
method.
If you have an initial state, you can use a BehaviorSubject
to initialise the subject and ensure new subscribers always receive a value.
If you don't have an initial state, but want to ensure new subscribers get the last emitted value on subscribing—if one exists—then you can use ReplaySubject
.
All of the values that go into a Subject
are of type T, where you have Subject<T>
. Therefore, in your case, everything going into the Subject
should be an AddressDto
.
If you have an initial address, then you would set up your BehaviorSubject
as follows.
// Somehow get the initial address.
const address = new AddressDto();
const test = new BehaviorSubject<AddressDto>(address);
// All subscribers will receive this address on subscribing.
// Something happens.
// There is another address; emit that.
const newAddress = new AddressDto();
test.next(newAddress);
// All new subscribers will receive newAddress on subscribing.
On the other hand, if you don't have an initial address you can use a ReplaySubject
as demonstrated below.
// Always emit the last address to new subscribers by intitialising it with the number 1.
// New subscribers won't receive an address until one is emitted.
const test = new ReplaySubject<AddressDto>(1);
// Something happens.
// Get the first address, and emit it.
const firstAddress = new AddressDto();
test.next(firstAddress);
// All current subscribers receive firstAddress.
// All future subscribers will receive firstAddress on subscribing
// Something happens.
const secondAddress = new AddressDto();
test.next(secondAddress);
// All current subscribers receive secondAddress.
// All future subscribers will receive secondAddress on subscribing.
You asked about storing the last value in a variable, which is ambiguous. I'm going to assume you mean at the source as that's more complex.
Once you get your head around the concept of Subject
and Observable
, you might understand the idea of the Observable
Pipe
. All sorts of stuff can happen inside a Pipe
; think of it as a series of steps of things that can happen to an object. It is similar to a series of chained array functions on a normal array in JavaScript.
One of the things you can do in a Pipe
is to perform "side effects" in a Tap
operator. This means that you can do stuff in the middle of a Pipe
while letting the data pass through it. To give two examples, you could store the value in a variable, or in localStorage
.
If you have control of what's going in the Subject
, it seems redundant to do this in a Pipe
; therefore, the following example shows how to cache the result of an HTTP request.
this.http.get(url).pipe(
// Transform the HTTP response into an object that is created.
map(response => this.mapResponseToMyClass(response)),
// Store the mapped object in a local property for later use.
tap(myClass => {
// Perform any 'side effect' actions you want, such as the below.
console.log(myClass);
// Store the value in a variable.
this.cachedMyClass = myClass;
})
);
'Piping' your own Subject
is no different. Everything that goes into a Subject
will go through a Pipe
and is then outputted to the subscriber.
private subject = new Subject<AddressDto>();
getPostcode(): Observable<string> {
// Reuse the local Subject. All subscribers to this function will receive addresses that have come through the Pipe.
return subject.pipe(
map(address => address.postcode),
// Store the last postcode in a local property.
tap(postcode => this.lastPostcode = postcode)
// The postcode is outputted here to all subscribers
).asObservable();
}
Upvotes: 13
Reputation: 44
Observable does not store value. You should have subscribed to Observable before you have push data in Observable stream to receive value. I think Your AddressObservable is an Observable, not BehaviorSubject. If you convert AddressObservable to BehaviorSubject. It will work. In case AsyncPipe it is working because it async pipe subscribe for the same.
Change AddressObservable to type: BehaviorSubject
Upvotes: 1