mfrachet
mfrachet

Reputation: 8932

Cyclejs and xstream not displaying anything

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 ?

Upvotes: 1

Views: 198

Answers (2)

bloodyKnuckles
bloodyKnuckles

Reputation: 12089

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}

Upvotes: 1

André Staltz
André Staltz

Reputation: 14004

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.

Upvotes: 2

Related Questions