# Using breathe.js

To use breathe.js, you split code into smaller chunks that don't have to get executed all at once. For instance, in traditional JavaScript, you may have a long looping function:

function longLoopingFunction() {
  var i;
  for(i = 0; i < 100000; i++) {
    trickyFunction();
  }
}

Here trickyFunction() runs 100,000 times, without letting any other code run or UI respond. But with breathe.js, the same code can be written as:

function breathableLongLoopingFunction() {
  return breathe.times(100000, function (i) {
    trickyFunction();
  });
}

Here the function also runs sequentially, but if it runs for too long (over 17 milliseconds by default), breathe.js relinquishes the main thread to allow other functions to run or UI to respond, then runs the remaining loop, repeatedly relinquishing if necessary.

# Breathable chains

Functions using breathe.js create breathable chains. Breathable chains don't immediately finish and therefor use asynchronous conventions of then and catch to run code and catch errors sequentially. It's very similar to a promise's control flow, with some deviations. To run code after a breathable function finishes, you can use the then method, like so:

breathableLongLoopingFunction().then(function () {
  console.log('All finished!');
});

Likewise, you can chain breathable code together within functions using the then method:

function breathableSequentialLongLoopingFunction() {
  return breathe.times(100000, function (i) {
    trickyFunction(); // run 100000 times
  }).then(function () {
    // then run this loop
    return breathe.times(300000, function (j) {
      anotherTrickyFunction(); // run 300000 times
    });
  }).then(function () {
    console.log('All done!');
  });
}

You can create breathable chains via the breathe.chain() constructor. Consider this code that has a sequence of computationally-intensive functions:

function longRunningFunction() {
  easyFunction();
  trickyFunction();
  difficultFunction();
  // ...
  almostImpossibleFunction();
}

This can be split into smaller bits of breathable code, with a breathable chain:

function breathableLongRunningFunction() {
  return breathe.chain()   // creates a breathable chain
    .then(function() {
      easyFunction();
      trickyFunction();
    }).then(function() {
      difficultFunction();
    }) //...
      .then(function() {
      almostImpossibleFunction();
    });
}

In this case, functions will run in sequential order, but if they took too long to run (over 17 milliseconds total, by default), breathe will relinquish the main thread to other code, before automatically reentering to where it left off.

# Invoking breathable functions in breathable chains

This code may still block the main thread if the individual subfunctions (e.g. almostImpossibleFunction) take a long time to execute. To alleviate this, functions can be further subdivided into breathable code; for instance trickyFunction, difficultFunction, and almostImpossibleFunction may be converted to breathable functions, like longRunningFunction was converted to breathableLongRunningFunction. In that case the invoking syntax slightly changes:

function breathableLongRunningFunction() {
  return breathe.chain()
    .then(function () {
      easyFunction();
      return breathableTrickyFunction(); // note the 'return'
    }).then(function () {
      return breathableDifficultFunction();
    }) // maybe have more functions/code ...
      .then(function () {
      return breathableAlmostImpossibleFunction();
    });
}

This allows for the subfunctions and code not to hog the main thread; if they take too long to execute, they will relinquish the main thread to other code.

# Accessing variables

In JavaScript, functions declared inside other functions can access the outer function's variables. This is particularly useful with breathe.js's extensive use of inner functions. If multiple functions are sharing a variable, make sure the variable is declared in a context shared by both variables.

function breathableMultiLegFunction() {
  var a = 2, b = 3;
  return breathe.chain().then(function () {
    var c = 4;
    // can access a, b, and c;
    b = a + 5;
  }).then(function () {
    // can access only a and b;
    console.log(b); // 7
  });
}

# Accessing results of breathable functions

In Promise conventions, the results of asynchronous code can be passed via a return statement in a then method. That result is then passed to the callback function in the next then method. breathe.js follows these conventions:

function breathableAddFunction(a, b) {
  return breathe.chain().then(function() {
    return a + b; // note the return is within a .then method
  });
}

// invocation:
breathableAddFunction(10, 12)
  .then(function (result) {
    console.log(result); // 22
  });

In cases where multiple breathable functions are called, with values returned, shared variables can be used to store their results for further computation.

function breathableAddFourFunction (a, b, c, d) {
  var aPlusB, cPlusD;
  return breathe.chain().then(function () {
    return breathableAddFunction(a, b);
  }).then(function (result) {
    aPlusB = result;
  }).then(function () {
    return breathableAddFunction(c, d);
  }).then(function (result) {
    cPlusD = result;
    return aPlusB + cPlusD;
  });
}
This can be compacted by assigning results and calling the next breathable function in the same .then statement, though this convention may be a little more confusing.
function compactAddFourFunction (a, b, c, d) {
  var aPlusB;
  return breathe.chain().then(function () {
    return breathableAddFunction(a, b);
  }).then(function (result) {
    aPlusB = result;
    return breathableAddFunction(c, d);
  }).then(function (result) {
    return aPlusB + result;
  });
}

# Using breathable loops

breathe.times loops are useful, but they replace only certain types of for loops.breathe.loop on the other hand, offers much more flexibility, similar to a while loop.

For example, consider this function:

function longWhileFunction() {
  var i = 0;
  while (++i < 2000 && condition()) {
    difficultFunction();
  }
}

Since anonymous functions can access non-local variables, it can be rewritten with breathe.js, simply as:

function breathableLongWhileFunction() {
  var i = 0;
  return breathe.loop(function() { return ++i < 2000 && condition(); }, function() {
    difficultFunction();
  });
}

The second argument for breathe.loop and breathe.times is the loop body; if it returns a promise or a breathable chain, it will wait until that code finishes before looping. This allows you to nest loops:

function breathableNestedFunction() {
  return breathe.times(100000, function (i) {
    return breathe.times(100000, function (j) {
      multidimensionalFunction(i, j);
    });
  });
}

#In summary: The anatomy of a breathable function

In general, functions can be subdivided into blocks of code, with variable declarations, synchronous code, and/or asynchronous code. The general pattern is:

function () {
  var variablesSharedInsideOfThisBlock;
  synchronousCode();
  return asynchronousCode();
}

You don't need to have both synchronous code or asynchronous code, though breathable code often involves subsequent code blocks. For instance, breathe.chain has a sequence of code blocks in then methods.

function breathableLongRunningFunction() {
  // this is a code block
  return breathe.chain() // asynchronous code
    .then(function () {
      // this is another code block
      easyFunction(); // synchronous code
      return breathableTrickyFunction(); // asynchronous
    }).then(function () {
      // yet another code block
      return breathableDifficultFunction(); // asynchronous
    }) // maybe have more functions/code ...
      .then(function () {
      // even another code block
      return breathableAlmostImpossibleFunction(); // asynchronous
    });
}
Likewise, breathe.loop takes a body as an argument, which is a code block:

function nestedLoop() {
  // one code block
  var running;
  running = true;
  return breathe.loop(function () { return running; }, function () {
    // another code block
    var i; // declaration
    i = 0; // synchronous code
    return breathe.loop(function () { return running && i++ < 50; },
      function () {
        // yet another code block
        running = doSomethingAwesome(c);
      }
    );
  });
}

If variables' values are shared by multiple blocks of code, their declaration should be moved to a context accessible to those blocks of code.

function sequentialLoops() {
  var a, b, c;            // variables to declare, shared by multiple blocks of code
  a = computeSomething(); // synchronous code
  return breathe.chain()  // return signifies the start of asynchronous code
    .then(function () {
      // another block of code
      c = a;                    // synchronous code
      return breathe.loop({     // asynchronous code
        condition: function () { return c > 0; }, // condition is always synchronous
        body: function () {     // yet another code block
          var d;
          d = c * a;
          draw(d);
          c--;
        }
      });
    }).then(function () {
      b = a + computeSomethingElse();
      // if it doesn't return a promise (or anything at all),
      // it's considered synchronous
    }).then(function () {
      return b; // return a value for sequentialLoops()
  });
}

# Pausing, unpausing, and stopping

Breathable chains have methods to pause, unpause, and stop their chains. They return promises that resolve after the chain successfully pauses, unpauses, or stops.
var chain = breathe.times(100000, function () {
  hardWork();
});

pauseButton.addEventListener('click', function () {
  chain.pause()
    .then(function () {
      console.log('Paused!')
    });
});

unpauseButton.addEventListener('click', function () {
  chain.unpause()
    .then(function () {
      console.log('Unpaused!')
    });
});

stopButton.addEventListener('click', function () {
  chain.stop()
    .then(function () {
      console.log('Stopped!')
    });
});

# Important considerations

# Converting synchronous code to breathable code

It's usually straightforward converting synchronous code to breathable code. Usually code can be mapped one-to-one, preserving the order, structure, and logic of the code. Here are some examples of converting code:



Changed Code Variable Declarations Loop Conditions Synchronous Code

# Basic Implementation

Synchronous:
function basicFunction() {
  var i;
  var j;
  i = getAmount();
  while(i++ < 200 && j !== 4) {
     j = doOneThing();
   }
  doAnotherThing(j);
  return yetAnotherThing(j);
}
Breathable:
function basicFunction() {
  var i;
  var j;
  i = getAmount();
  return breathe.loop(function () { return i++ < 200 && j !== 4;}, 
    function () {
      j = doOneThing();
    }
  ).then(function () {
    doAnotherThing(j);
    return yetAnotherThing(j);
  });
}



Changed Code Variable Declarations Loop Conditions Synchronous Code

# Sequential Loops

Synchronous:
function sequentialLoops() {
  var i;
  var j;
  i = getAmount();
  while(i < 200 && j !== 4) {
     j = doOneThing();
     i++;
    }
  doAnotherThing(j);
  i=0;
  while(i < 200 && j > 4) {
     j = doYetOneMoreThing();
     i++;
    }
  return yetAnotherThing(j);
}
Breathable:
function sequentialLoops() {
  var i;
  var j;
  i = getAmount();
  return breathe.loop(function () { return i < 200 && j !== 4;}, 
    function () {
      j = doOneThing();
      i++;
    }
  ).then(function () {
    doAnotherThing(j);
    i=0;
  }).then(function () {
    return breathe.loop(function () { return i < 200 && j > 4; }, function() {
      j = doYetOneMoreThing();
      i++;
    });
  }).then(function () {
    return yetAnotherThing(j);
  });
}


Changed Code Variable Declarations Loop Conditions Synchronous Code

# Nested Loops

Synchronous:
function nestedLoops() {
  var i;
  var j;
  var k;
  i = getAmount();
  while(i < 200 && isGood(j)) {
    j = doOneThing();
    k = 0;
    while(k < 200 && j > 4) {
      j = doYetOneMoreThing();
      k++;
    }
    i++;
  }
  doAnotherThing(j);
  return yetAnotherThing(j);
}
Breathable:
function nestedLoops() {
  var i;
  var j;
  var k;
  i = getAmount();
  return breathe.loop(function () { return i < 200 && isGood(j);}, 
    function () {
      j = doOneThing();
      k = 0;
      return breathe.loop(function() { return k < 200 && j > 4; }, function(){
          j = doYetOneMoreThing();
          k++;
        }).then(function(){
          i++;
        });
    }
  ).then(function () {
    doAnotherThing(j);
    return yetAnotherThing(j);
  });
}