banica
v1.0.4
Published
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.
Downloads
16
Maintainers
Readme
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!`));