0

I’m new to rxjs and stuck with a simple task. Say I have one stream with array:

var array$ = Rx.Observable.just([1, 2, 3, 4, 5]);

And I have another stream of clicks:

var click$ = Rx.Observable.fromEvent(
  document.getElementById('button'),
  'click'
)

How do I combine them to get each element from array on each click (1 on first click, 2 on second and so on)?

3 Answers 3

1

There are many ways to do this. A simple one is as follows:

var click$ = Rx.Observable.fromEvent(
  document.getElementById('button'),
  'click'
);

var combined$ = otherButtonClick$.flatMapLatest(function (){
 return click$
  .map(function(value, index){return index;})
  .withLatestFrom(array$, function(index, array){return array[index];})
 });

Is there a bigger goal you are trying to achieve through this?

Sign up to request clarification or add additional context in comments.

4 Comments

Yeah, it seems like what I’m looking for, but I have some concerns, namely: is this index from map goes infinitely from 0? I’m getting an array from server and when I click another button the array stream emits another array and I want to be able to traverse it from 0-index again.
updated the code to reflect the new information. Basically to reset the index counter, it is necessary to use the flatMapLatest operator. Try it, I can see some possible issues but the best is to try first.
If that does not work, you might have to provide more code to understand how your array streams are generated. The code above might not work if when the other button is clicked, the array$ stream has not emitted yet its new value (because we fetch the latest value, so if that latest value hasn't changed yes, then we failed here). In which case a turnaround should be to replace withLatestFrom by combineLatest.
Sorry for the delay, I was able to get to the code only now. And actually your first version is working fine, because when I click other button I create new streams (which are new dataflow components from cycle.js), so I’m marking your answer as correct, thank you.
0

just() is going to return the whole array. You want to use fromArray() to create the first stream. Then you can zip the two arrays together to get the next element in the array stream:

var array$ = Rx.Observable.fromArray([1, 2, 3, 4, 5]);

var click$ = Rx.Observable.fromEvent(
  document.getElementById('button'),
  'click'
).zip(array$, function(click, num) {return num}).subscribe(function(el){
  return el;
})
<script src="//cdnjs.cloudflare.com/ajax/libs/rxjs/2.5.3/rx.all.js"></script>
<button id="button">
  button
</button>

2 Comments

Hm, I’m getting an array from server in the stream of http request, so this is not quite what I want
In either case, just() isn't going to do it for you. You can still zip the http stream in with the click stream.
0

You'll need to use some back pressure mechanism like:

  • Example 1:

    var array$ = Rx.Observable.from([1, 2, 3, 4, 5]).controlled;
    
    var click$ = Rx.Observable.fromEvent(
      document.getElementById('button'),
      'click'
    )
    
    array$.subscribe(function(value){ console.log(value); });
    
    click$.subscribe(function(){
      array$.request(1);
    })
    
  • Example 2 (Using combine)

    var array$ = Rx.Observable.from([1, 2, 3, 4, 5]).controlled;
    
    var click$ = Rx.Observable.fromEvent(
      document.getElementById('button'),
      'click'
    )
    
    click$.flatMap(function(){
      return Rx.Observable.create(function(observer){
        array$.first().subscribe(observer);
        array.request(1);
      }
    })
    .subscribe(function(value){ console.log(value); });
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.