-
Notifications
You must be signed in to change notification settings - Fork 330
There is no getLatestValue method available and will not be either. You get the value by subscribing to the stream/property (using onValue) and handling the values in your callback. If you need the value of more than one source, use one of the combine methods.
Bacon.js works so that Properties and EventStreams connect to their sources (such as jQuery events) when they have at least one listener. They also automatically disconnect when there are no listeners. So, subscribing to the stream or property is important also from this aspect.
You have a situation like this:
var bus = new Bacon.Bus;
var property = bus.toProperty('FIRST');
bus.push('SECOND');
property.onValue(function(val) {
console.log(val);
});
You'd like the console to log 'SECOND' but it logs 'FIRST' instead.
What's happening here is that your Property won't get updated when there are no listeners. Before you add an actual listener using onValue, the Property is not active; it's not listening to the underlying Bus. It ignores input until someone's interested. So it all boils down to the "laziness" of all Bacon streams and properties. This is a key feature too: the streams automatically "plug in" to their sources when a listner is added, and "unplug" when there are no more listeners.
No. Sorry. Not smart enough to do that yet.
Assume you have properties A and B and a a property C = A + B. When the value of A changes from a1
to a2
and B changes from b1
to b2
simultaneously, you'd like C to update atomically so that it would go straight from a1+b1 to a2+b2. Unfortunately, Bacon.js does not recognize simultaneous events/updates and you'll get a transitional state when C=a2+b1 or C=a1+b2.
It would be nice if the "framework" had support for that but I haven't figured out a generic way for this yet. The thing is that Bacon.js uses the same "subscribe" mechanism internally that it provides to application code. This means that it has no means to coordinate updates that involve multiple streams/properties.
If you figure out a generic way to do this, please share your thoughts.
So far my impression is that you can use FRP on both the small scale and the large, but that it is not a magic bullet for solving your problems. You'll still have to think about application architecture or you'll run into similar problems (spaghetti code) as with other paradigms.
You might consider applying an MVC-style architecture to your application and use Bacon.js streams and properties for communication between components. Your Models may be Streams, Properties or more complex objects exposing Streams, Properties and Buses. Have a look at one of my blog posts on TodoMVC with Bacon.js for some more information on this.
It's up to you. You may apply FRP to solve some isolated problems in your application and lose nothing. Or you may model your application in a new way. If you, for instance, ditch MVF frameworks and use Bacon+jQuery instead, you'll get a somewhat simpler solution, less indirection and better composability. Then again, you'll lose the specific benefits of the framework. For instance, Backbone Collections are great and if you master them, you don't necessarily want to lose them. The good news is that you don't have to throw good things away. Bacon.js is not a framework, so it plays ball with frameworks. Have a look at how @pyykkis combined Bacon with Backbone collections. Please use any combination you like and tell me how you did it and how did you succeed :)
It is in production. There are no known bugs. 182 tests, 1173 assertions for 916 LOC CoffeeScript code. You do the math.
I'm considering the 1.0 label any day now, and no API changes are to be expected. Some were done recently for the 0.1.0 release (see release notes)
There are no benchmarks that would compare a large-scale Bacon.js solution to something else as of yet. Neither have I ever heard of anyone experiencing Bacon.js related performance problems. The system is not in fact very complicated, so you shouldn't experience major overhead in comparison with, for instance, just using jQuery events. In my Worzone game I shamelessly throw events around for every little thing that happens in the game (for instance, when a bullet moves a pixel), and according to my profiling in Chrome, the Bacon.js dispatching mechanism doesn't really show in the results. But that's hardly a real performance test. I didn't experience notable performance gain or loss when I converted the game from RxJs either. So, for me, it looks like perf's o.k.
There'a a related Issue related to performance testing.
Stepping into FRP from imperative programming is a big change, and will definitely take some time to grasp. However, if you're familiar with FP list handling (map, filter, flatMap...), you'll find similarities. I've had a couple of hands-on Bacon.js workshops so far and every single participant was able to complete at least a couple of features on their own (well, I gave some hints for sure).
Try it out and tell me.
Currently, Bacon.js supports creating EventStreams from jQuery events, DOM EventTarget, Node.js EventEmitter, jQuery Deferred, or any polling function. Have a look at the readme.
If you need to plug in other sources, creating an EventStream yourself isn't actually very hard. Have a look at the source code where all of these converters are implemented for reference.
One option is always to create a Bus and just push events into that:
var bus = new Bacon.Bus()
bus.push("event")
I like coffeescript more than JS, but notice all your examples are in JS. Would I be better off just using JS with Bacon?
Bacon.js itself is written in CoffeeScript, which is better-suited for functional programming than Javascript, because of the nicer lambda syntax. Go ahead with CoffeeScript, should work fine. The examples are in JavaScript because that's the lowest common denominator; everyone reads JS.
Just like you'd use any other Javascript library.
Bacon.js is a CoffeeScript library that's build into Javascript using Grunt. You can use one of the built js files as you like, or you can use it as a dependency in your Node.js, Yeoman or Bower project. See readme.
Bacon.js is inspired by RxJs and has similar concepts. The main difference in the design is the existence of two flavors of Observables: EventStream and Property, each of which have clearly defined semantics. The RxJs Observable does not tie the semantics as tightly. For instance, in RxJs there are "hot" and "cold" observables that behave differently even though the expose the same Observable interface.
Also, Bacon.js is fully open-source and has (arguably) better documentation.
Doesn't this turn "callback" hell into "mapfiltercombine" hell? How I will integrate a new developer to my FRP code?
What FRP does to callback hell is the same thing that FP does to for-loops. Some may argue that for-loops are easier to read than a map-filter-combo. It's the same thing with all new tools. Some managers fear that their employees will never learn Scala, so everything has to be written in Java. Would you still like to write code in Cobol?