baconjs / bacon.js

Functional reactive programming library for TypeScript and JavaScript
https://baconjs.github.io
MIT License
6.47k stars 330 forks source link

Getting value of a property and understanding FRP/RP #478

Closed gyzerok closed 9 years ago

gyzerok commented 9 years ago

Hello, guys!

I'm new to FRP (or RP, dont know exactly) and want to get in with bacon. The first thing I really cant understand is the Property. Documentations says:

One of the common first questions people ask is "how do I get the latest value of a stream or a property". There is no getLatestValue method available and will not be either. You get the value by subscribing to the stream/property and handling the values in your callback. If you need the value of more than one source, use one of the combine methods."

So what if I want to know its value in some later time after it arrives? What should I do? As I understand documentation says that I can get this value using some technics, but there are no examples describing them.

As most of bacon users I'm coming from MVC world. So the other question I have is: "How to organize large application?". All the examples I found are "one file program". What are the common technics to develop an app with several modules?

I there any guides from which I can get more solid knowledge about what FRP (or RP) is and how to use it in every day development?

benjycui commented 9 years ago

Here is an introduction of RP -> https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

gyzerok commented 9 years ago

Thank you @benjycui I've already read this. The problem about such topics is that they share same examples. I need something more solid.

raimohanska commented 9 years ago

Hello! Very good questions indeed!

If you want to use the value of a Property x later, you should probably define "later" as an event in some EventStream e. Now, you can, for example, use x.sampledBy(e) to get an event that has the value of x when e occurs.

How to organize large application? That seems to be a topic not very well covered in the internets and rewards a blog post or two. Maybe my next post will be on this. Anyway, what I personally do is something like this.

As with any other tecnology, I split my application into independent components with a single responsibility. I use EventStreams and Properties to connect the components together. This comes quite naturally when they are also internally composed from the same. For example, a ShoppingCart model component might look like this.

function ShoppingCart(initialContents) {
  var addBus = new Bacon.Bus()
  var removeBus = new Bacon.Bus()
  var contentsProperty = Bacon.update(initialContents,
    addBus, function(contents, newItem) { return contents.concat(newItem },
    removeBus, function(contents, removedItem { /* omitted */ }
  return {
    addBus: addBus,
    removeBus: removeBus,
    contentsProperty: contentsProperty
  }    
}

Now the external interface of this component exposes the addBus and removeBus Buses where you can plug external streams for adding and removing items. It also exposes the current contents of the cart as a Property.

Now you may define a view component that shows cart contents:

function ShoppingCartView(contentsProperty) {
  function updateContentView(newContents) { /* omitted */ }
  contentsProperty.onValue(updateContentView)
}

And a component that can be used for adding stuff to your cart:

function NewItemView() {
  var newItemProperty // property containing the item being added
  var newItemClick // clicks on the "add to cart" button
  var newItemStream = newItemProperty.sampledBy(newItemClick)
  return {
    newItemStream: newItemStream
  }
}

And you can plug these guys together as follows.

var cart = ShoppingCart([])
var cartView = ShoppingCartView(cart.contentsProperty)
var newItemView = NewItemView()
cart.addBus.plug(newItemView.newItemStream)

I hope this helps!

gyzerok commented 9 years ago

Big thanks, @raimohanska! This helps a lot!

There are a big lack of examples of using reactive programming for non-simple apps especially for back-end. I don't know if reactive programming is the paradigm of the future, but I think that today any engineer must to be on the edge of technologies. So I'm trying to dive in.

Now I'm developing a simple rsa chat application just for practise. And want to use Bacon for both front-end and back-end. It would be great if you can review my code as soon as it would be ready so your advises can improve both my understanding of FRP and code quality. I suppose we can then add this code as one more solid example of using Bacon. You can find my code in https://github.com/gyzerok/reactive-cryptochat. Tell me if it's ok to contact you for reviewing as soon as its ready.

If we do so with my little chat I can try to develop more complex single page application with different routes and views on front-end and some business logic on back-end.

raimohanska commented 9 years ago

I strongly prefer questions on Stack Overflow or Google Groups to personal email and usually don't have the time to review people's code for free :)

RoboTeddy commented 9 years ago

I have viewmodels that look very similar to @raimohanska's ShoppingCart. I create buses for streams of requests from the user, and then compose those streams together into properties, and expose both the buses and the resultant properties.

I then pass the properties into React (via) https://github.com/irskep/BaconReactMixin to render the view declaratively. If a property changes, the DOM updates accordingly.

gyzerok commented 9 years ago

@raimohanska, mb you can advise someone who can help me?

@RoboTeddy, thank you for helping! Can you share your code?

raimohanska commented 9 years ago

Btw, I upgraded my answer above into a blog post: http://baconjs.blogspot.fi/2014/12/structuring-real-life-applications.html

gyzerok commented 9 years ago

@raimohanska it would be even better if you add this in the project wiki so everyone can find it later easily and dont have to scroll down the blog for ages :)

phadej commented 9 years ago

... or bootstrap the cookbook or tutorials on the website :)

raimohanska commented 9 years ago

Good points. I guess the site might be the place for articles like this.