Cyclejs and xstream not displaying anything

195 Views Asked by At

I m trying to create a stream from an array logging inside of its map operator but it seems that something goes wrong in my code and I can't point it out...

import {Slider} from './slider/slider'
import xs from 'xstream'

export function App(sources) {
    const props = {
        marbles$: xs.fromArray([{
            color: 'red',
            x: 0
        }, {
            color: 'blue',
            x: 20
        }])
    }

    props.marbles$.map(item => {
        console.log(item) // nothing displayed on here
        return item
    })
    return Slider(Object.assign(sources, {props}))
}

On this little code, I m simply creating a props object containing a marbles$ stream from an array.

Just below I try to log on each item in the stream but nothing happens, and I don't understand why.


Plunker here : https://plnkr.co/edit/6uMsLIl1Edd5x670OqHa?p=preview

Nothing to show on the HTML file, only on the JS file

Any idea ?

2

There are 2 best solutions below

0
bloodyKnuckles On BEST ANSWER

As stated in the xstream docs, streams are idle (not executed) until they get their first listener, which is accomplished with the addListener method.

Notice below that the props.marbles$.map stream is assigned to variable y. Then the y.addListener method is invoked. When addListener is called, the props.marbles$.map method is finally executed.

const props = {
  marbles$: xstream.Stream.fromArray([{
    color: 'red',
    x: 0
  }, {
    color: 'blue',
    x: 20
  }])
}

const y = props.marbles$.map(item => {
    console.log('map', item)
    return item
})

y.addListener({})

Outputs in the console:

map > Object {color: "red", x: 0}
map > Object {color: "blue", x: 20}

Alternatively you can put the console.log in the next property of the listener instead of the map method:

const y = props.marbles$.map(item => {
  return item
})

y.addListener({
  next: item => console.log('listener', item)
})

Outputs in the console:

listener > Object {color: "red", x: 0}
listener > Object {color: "blue", x: 20}

OR, as André suggested, you can use xstream debug:

const props = {
  marbles$: xstream.Stream.fromArray([{
    color: 'red',
    x: 0
  }, {
    color: 'blue',
    x: 20
  }]).debug('debug 1')
}

const y = props.marbles$.map(item => {
  return item
}).debug('debug 2')

y.addListener({})

Outputs in the console:

debug 1 > Object {color: "red", x: 0}
debug 2 > Object {color: "red", x: 0}
debug 1 > Object {color: "blue", x: 20}
debug 2 > Object {color: "blue", x: 20}
1
André Staltz On

If you call props.marbles$.map(....) without capturing its output, you will have created a stream that is simply dropped on the floor and never used. Because this is just functional programming, it's the same case as const y = Math.round(x) but written as Math.round(x). It would take the number x, return that rounded to the nearest integer, and drop the result.

Since you wanted to just debug the value with a console, I recommend using the xstream operator debug(). Just add it to the chain of operators:

const props = {
    marbles$: xs.fromArray([{
        color: 'red',
        x: 0
    }, {
        color: 'blue',
        x: 20
    }]).debug()
}

If you use some linting tools such as https://github.com/bodil/eslint-config-cleanjs, it would have warned you of a statement with unused return value.