Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS: How to wrap and observe string for changes?

RxJS: How do you wrap a primitive type such as a string in an Observable and listen to changes to that primitive?

Consider the following example. setTimeout simulates some external event that changes the string s. However, the console.log only fires once and not after setTimeout is called. Why is that?

let s = "Hello World";
Observable.of(s).subscribe(val => {
    console.log(val);
});
// some external event changes variable s
setTimeout( () => {
    s = "Wat?";
}, 1000);
// Output: prints "Hello World" to console, but not "Wat?"

This question might sound a bit dumb, but I searched for 2 hours through all kinds of RxJS docs and examples and most of them play with Arrays or Objects. This is not what I want. I don't want to change attributes, functions, arrays or anything like that. Just a plain string or boolean or number.

like image 981
ntaso Avatar asked Dec 20 '16 20:12

ntaso


Video Answer


2 Answers

I do realize that this question has an accepted answer but here is the proper way to observer a string for changes using RxJS.

Create a variable for type ReplaySubject

stringVariable$: ReplaySubject<String> = new ReplaySubject<String>();

Assign all new values to stringVariable via a function to catch the update event.

assignNewValue(newValue: String) {
    this.stringVariable$.next(newValue);
}

Subscribe to this Observable

stringVariable$.subscribe((newValue: String) => {
    console.log(newValue);
});

Alternatively you can use a BehaviourSubject if your string variable has a initial value to start with.

like image 173
Giridhar Karnik Avatar answered Oct 03 '22 01:10

Giridhar Karnik


You are thinking about streams incorrectly. The whole point of the stream is that you should not be mutating objects directly (strings can't actually be mutated as @Pointy already mentioned but this is a more general point).

You need to shift your thinking to seeing data as immutable and the stream as representing the change which your react to in the subscriber.

In your example, if you wanted to "mutate" a string, what you are really trying to do is capture a set of changes and surface them through the next handler of the subscribe method. Where those changes come from is irrelevant from the string's perspective, it only cares that events are being passed through it.

i.e. I could do the following to emit different strings:

Rx.Observable.timer(1000)
  .mapTo('Wat')
  .startWith('Hello World!')
  .subscribe(x => console.log(x));

What you need to determine is what the source of your changes is and what events it should emit. From there Rx can help you massage that data into something that you can use downstream.

like image 36
paulpdaniels Avatar answered Oct 03 '22 03:10

paulpdaniels