banica v1.0.4
Banica
Handle async processes like a boss. Implementation of the command pattern using generators. Or in other words a redux-saga but without the Redux bit.

- Read the story of the library
- CodePen to play with codepen.io/krasimir/pen/YEvNqx
Installation
yarn add banica or npm install banica -S. The library is available also as a single JavaScript file here.
Usage
The library exports just two merhods call and run. call is used to wrap your function calls so the run function recognizes them as commands. That run function accepts a generator function or a created generator. For example:
import { call, run } from 'banica';
const isItTimeForBreakfast = () => true;
const getFood = () => new Promise(resolve => {
  setTimeout(() => resolve('banica'), 1000);
});
const eat = what => `I'll take ${ what } for breakfast!`;
const goodMorning = function * () {
  const ready = yield call(isItTimeForBreakfast);
  if (ready) {
    const food = yield call(getFood);
    const message = yield call(eat, food);
    console.log(message); // I'll take banica for breakfast
  }
}
run(goodMorning).then(() => {
  console.log(`Oh, I'm full. I can't eat anymore.`);
});Error handling
Just wrap the yield statements into a try-catch block. An error is send back to your generator in the following cases:
- Your function throws an error
- Your function returns a promise that gets rejected
const broken = function () {
  throw new Error('Ops, it is broken!');
}
const brokenAPI = function () {
  return new Promise((resolve, reject) => {
    reject(new Error('Ops, the API is broken!'));
  });
}
const program = function * () {
  try {
    yield call(broken);
  } catch (error) { ... } // "Ops, it is broken!" error
  try {
    yield call(brokenAPI);
  } catch (error) { ... } // "Ops, the API is broken!" error
}API
call(<func or generator function>, ...args)
call function accepts a function or generator function and arguments that need to be passed down. For example:
const formatMessage = name => `Hello ${ name }`;
//...later in a generator
yield call(formatMessage, 'John');
or
const getGreeting = () => 'Hello';
const formatMessage = function * (name) {
  const greeting = yield call(getGreeting);
  return `${ greeting } ${ name }`;
}
//...later in a generator
yield call(formatMessage, 'John');What you can yield call is:
- A function
- A function that returns a promise
- A generator function
The call method returns an object of the form
{ type: 'call', func: <your function here>, args: <your arguments here> }run(<generator or generator function>)
Either create your generator upfront or send the generator function.
function * generator() {
  // ...
}
run(generator());
// or
run(generator);The run method returns a promise that gets resolved when your generator is completed:
run(generator).then(() => console.log(`Job's done!`));