Hacker News new | past | comments | ask | show | jobs | submit login
Transparent Reactive Programming (github.com/meteor)
41 points by primigenus on March 14, 2015 | hide | past | favorite | 6 comments



I've been playing with/learning meteor for the past week. The reactivity is no doubt a great feature. It's a great joy to develop with meteor too, with hot code pushes, the app automatically updates to include your file changes on the fly. It's great.

The ability to create custom reactive objects is sweet. Plus you can stop reactivity on the fly. Thus far I'm really enjoying it.


Meteor's reactive style is so incredibly powerful that it's useful even outside the Meteor ecosystem. In case anyone is looking to use this, I made a fork of Meteor's Tracker for use in any Node.js or browser app: https://www.npmjs.com/package/trackr (shameless plug)


I'm quite tired so I might be mistaken here, but autorun reminds me of Knockout's computed properties.

  function viewModel() {
    this.observable = ko.observable();
    this.updateWhenObsChanged = ko.computed(function() {
      console.log(this.observable());  // logs whenever the observable changes
      return this.observable();  // see template example below
    });
  }
  ko.applyBindings(viewModel);
Any observables used in a computed property are automatically watched. The computed property can contain any JS code; it makes the function inside reactive.

Knockout also has a built in templating library where you can do things like: <p data-bind="text: updateWhenObsChanged"></p>

It seems like in this library, one area that's more flexible than KO is that you can create various reactive data sources. However, in KO you can essentially do the same thing by updating an observable. For instance, you could have this.webSocketResponse = ko.observable() and call it with a new value for every websocket response you give.

Now for me, the step beyond this is a library like Reactive Extensions (RxJS for Javascript) which instead of having stateful observables gives you async streams of events. For instance, say that you have two buttons, #1 and #2, and you want to do something when button one is pressed before button two:

  var buttonOne = $('#1');
  var buttonOneClickStream = Rx.Observable.fromEvent(buttonOne, 'click');
  var buttonTwo = $('#2');
  var buttonTwoClickStream = Rx.Observable.fromEvent(buttonTwo, 'click');
  var lastTwoClicks = buttonOneClickStream
    .map(function () { return 1; }) // clicking button one produces a 1
    .merge(  // merge buttonOneClickStream's output with the buttonTwoClickStream
      buttonTwoClickStream.map(function() { return 2; }) // clicking button two produces a 2
    )
    .bufferWithCount(2); // emit an array of two values once we have two values from our merged streams
  var firstThenSecond = function (arr) {
    return arr[0] === 1 && arr[1] === 2;
  };
  var clickedFirstThenSecond = lastTwoClicks  
    .filter(firstThenSecond);  // only emit events that match our filter
  var notifyOnSuccess = clickedFirstThenSecond.subscribe(function() {
    console.log("woot");
  });
The nice thing about this approach is that you can build up a variety of streams and merge them in a reusable and functional way. While this is possible in KO, I find that unless I'm very disciplined I ended up with a mess of computed properties scattered throughout my app. Since in KO we are using the observer pattern, which is stateful, this can cause some complexities. But with stateless streams, we have a more declaritive and perhaps even "imperative" approach.

The step beyond this it to tie these streams into something more advanced than JQuery, like virtualdom. I started working on this only to find someone else has already accomplished a lot more than me in https://github.com/staltz/cycle However, I think I might like a template-based approach using something like handlebars.

Anyways I'm quite tired so I might be mistaken in my assesment of this library. But I think anyone interested in reactive programming might like KO, RxJS, and Cycle. KO's worked quite nicely for me, despite my complaints about the limitations of stateful observers.

Complete example of RxJS: http://jsfiddle.net/bjhyvvjs/

How to grok reactive programming: https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

Why React.js isn't actually reactive: http://staltz.com/dont-react/#/

Edit: Argh I'm so sorry about the bad code rendering... I forgot to set translate_tabs_to_spaces in Sublime Text :( It should be good now!


Hrm, do you mean that you use RxJS with knockout to alleviate the mess of computed properties? Or switch to RxJS/Cycle entirely?


I haven't actually tried using both RxJS and Knockout together, but it's something I'm thinking about doing. It might seem strange to merge these two different approaches, but I'm a fan of MVVM (which KO espouses) and of KO's templating and component functionality. To get it working, the callback in an RxJS subscribe method would set a KO observable, which would then be bound to the view.

IIRC KO's author is familiar with RxJS; he made KO and reduced the concepts to observables (of which there are similar objects in RxJS) and computed properties as he felt it was more straightforward for the typical dev in not requiring one to make the paradigm shift to stream composition.

I think that KO, especially when using components for encapsulation and reuse, can be a very powerful tool. But once I started combining KO with Bluebird for promise combinators, I started to understand the benefits of the stream-based approach better (in RxJS promises are just another source of events, which is a very powerful tool that I should have mentioned in the original post).


It seems like you'd have to avoid having async code inside of an autorun, otherwise when it resumes `Tracker.currentComputation` could be different?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: