Brendan Brendan - 3 months ago 11
Javascript Question

What to do when one stream depends on the value from another?

I'm new to Rx.js and looking for some basic help with FRP concepts. I have one stream using

generateWithRelativeTime
that keeps a game loop running, and a stream that keeps track of the screen resolution. My problem with my current code is that my game loop only runs when my screen resolution changes.

The stream generated by my model function requires the latest value from res$.

function model(res$) {
return res$.map(res => {
const rows = ceil(res[1] / CELL.HEIGHT)+1
const cols = ceil(res[0] / CELL.WIDTH)+1

return Observable.generateWithRelativeTime(
initWorld(rows, cols, 1.618),
noOp,
world => step(world),
noOp,
_ => 100,
Rx.Scheduler.requestAnimationFrame
).timeInterval()
});
}

function intent() {
return Observable.fromEvent(window, 'resize')
.map(e => [e.currentTarget.innerWidth, e.currentTarget.innerHeight])
.debounce(100, Rx.Scheduler.requestAnimationFrame)
.startWith([window.innerWidth, window.innerHeight])
}

model(intent())

Answer

Welcome to the joy of FRP. As it is, it is difficult to understand your question. How What to do when one stream depends on the value from another? is connected to My problem with my current code is that my game loop only runs when my screen resolution changes.? You give the actual behavior, what is your expected behavior?

For my limited understanding of the question, I think that you need to replace this line return res$.map(res => { by return res$.flatMapLatest(res => {, i.e. use the operator flatMapLatest instead of the map operator.

To understand the flatMap operator, I recommend you to review the following resources : The introduction to reactive programming you've been missing, the illustrated marbles and the official documentation.

PS : I see that you seem to follow a MODEL-VIEW-INTENT architecture. Out of curiosity, are you experimenting with cyclejs?