Control Flow

nFlow allows you to create asynchronous event trees that represent complex multi-step actions.

Model == Dispatcher == Event

The main feature of the nFlow architecture is that everything shares the same object type. Whether it's an event, store, model or controller - it's just a flow object, so the API is the same and the behaviour is the same.

This gives you great flexibility - you decide where and how you use nFlow. It's ok if your app already uses a Store/Model or an MVC framework - nFlow will only fill in the gaps, you will not need to change your code.

Dispatching events on events

Since in nFlow events are also flow objects, this allows you to "respond" to events by dispatching further events on them:

// mum.js
f.create('mum')
  .on('i-am-hungry', function(){
    this.emit('order-pizza', money)
  })

// pizza-shop.js  
f.create('shop')
  .on('order-pizza', function(money){
    //...bake pizza
    this.emit('pizza-ready', {pizza})
  })

// me.js
f.create('me')
  .on('pizza-ready', eat)
  .emit('i-am-hungry')

Since the event tree is just the same as the flow tree, you can traverse it in the listener. This allows you to "go back in time" and find out what triggered the event.

The .parent() API steps up in the event tree an returns the upstream event that triggered the current one. You can event access the payload of upstream events using the .data() API.

To extend the previous example:

function eat(pizza){
  this // this is the 'pizza-ready' event
  this.data() // returns the pizza

  // why is this pizza here? - because it was ordered:
  this.parent() // returns the 'order-pizza' event
  this.parent().data() // returns {money}

  // why was the pizza ordered? - because I was hungry:
  this.parent().parent() // returns the 'i-am-hungry' event
}