2011-02-18

Failing with RX-JS

The first-ever example I've seen of Reactive Extensions for Javascript is the example, where you've got these +/- buttons that you can use to increment/decrement a counter:


The code is nice and elegant as in



$(function() {
function always(x) { return function(_) { return x }}
var incr = $('#incr').toObservable('click').Select(always(1))
var decr = $('#decr').toObservable('click').Select(always(-1))
var series = incr.Merge(decr)
.Scan(0, function(total, x) { return total + x })
series.Subscribe(function (total) { $('#count').html(total) })
})


Great, isn't it? Well, I wasn't quite impressed. This is a toy example and doesn't really show the real power of RX. However, what do you think will happen with the following addition:



  $('#moar').click(function(){ 
    series.Subscribe( function(total) {$('#count2').html(total)})
  })

I'd expect that after clicking on the "moar" button, a duplicate counter would appear, showing the same number as the first one. However, it'll look like this:


How come? It seems that when a new Subscriber is added, it will get a new copy of the Observable series, starting from zero. It seems that the accumulator in the Scan combinator is not shared by subscribers. I guess it's logical but it certainly took my by surprise. It doesn't feel right that different observers of the same Observable see different values. What do you think? 

This can be fixed quite easily though:

  var series = incr.Merge(decr)
    .Scan(0, function(total, x) { return total + x })
    .Publish()
  series.Connect()

Not hard per se, but the real problem with RX is that you have to know all these tricks and there's no-one there to teach you (except some brave bloggers). Where is the public API documentation? Well, it's there for sure. Provided in Windows Help File format, in the file RxJS.chm that's bundled with the distro. Who uses .chm files for documentation?

According to Microsoft's fine documentation, the Publish() method "Returns a connectable observable sequence that shares a single subscription to the underlying source". It doesn't say that you have to call Connect() too to make it actually work. But hey, it doesn't say much else either. 

I HATE the way this library is documented. It makes me feel the authors are either cocky or stupid. The latter seems impossible regarding the quality of the actual code.

EDIT: Sorry for the last line. I've got huge respect for the Rx team and by now they've improved documentation a lot too, but that was the situation and those were my feelings at the time I wrote this post.

9 comments:

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete
  4. This comment has been removed by a blog administrator.

    ReplyDelete
  5. This comment has been removed by a blog administrator.

    ReplyDelete
  6. This comment has been removed by a blog administrator.

    ReplyDelete
  7. This comment has been removed by a blog administrator.

    ReplyDelete
  8. This comment has been removed by a blog administrator.

    ReplyDelete
  9. That is really cool. Thanks for finding it. Some really good ideas there, this is going to be a real time sink. I am a china tour lover,You can learn more: China vacation packages | China tour operator | China travel packages

    ReplyDelete