ycall
Version:
Use generators and yield to write regular callback-based functions
197 lines (137 loc) • 5.4 kB
Markdown
Simplifies interop between [co](https://www.npmjs.com/package/co) (promise / generator-based) async functions, and async callback-based functions (both node-style nodebacks where the first parameter is an error, and regular callbacks).
* Write callback-based async functions using generators (using `cfy`). Can also write node-style ("nodeback") async functions (using `cfy_node`). If the resulting function is not passed a callback, an ES6 Promise is returned.
* Can `yield` callback-based functions in generators (using `yfy`), as well as node-style nodeback-based functions (using `yfy_node`).
* All features of generators wrapped with [co](https://www.npmjs.com/package/co) (such as yielding Promises) can be used generators wrapped with `cfy` and `cfy_node`.
## Install
```
npm install cfy
```
## Usage
For the purpose of these examples, we assume you have required the library as follows:
```javascript
var {cfy, cfy_node, ycall, ycall_node, yfy, yfy_node} = require('cfy');
```
```javascript
var {cfy} = require('cfy');
var cfy_example = cfy(function*() {
var result = yield Promise.resolve(5); // 5
return result;
});
cfy_example(function(x) { console.log(x) }); // 5
cfy_example().then(function(x) { console.log(x) }); // 5
```
```javascript
var {cfy, yfy} = require('cfy');
var yfy_example_with_arguments = cfy(function*(a, b) {
var result = yield yfy(add_async)(5, 1); // 6
return result + a + b;
});
yfy_example_with_arguments(2, 7, function(x) { console.log(x) }); // 15
yfy_example_with_arguments(2, 7).then(function(x) { console.log(x) }); // 15
```
```javascript
var sleep = cfy(function*(time) {
function sleep_base(msecs, callback) {
setTimeout(callback, msecs);
}
yield yfy(sleep_base)(time);
});
var sleep_example = cfy(function*() {
yield sleep(3000); // sleeps for 3 seconds
return 7;
});
sleep_example(function(x) { console.log(x) }); // 7
```
`cfy` creates a callback-style function from a generator
```javascript
var cfy_example = cfy(function*() {
var result = yield Promise.resolve(5); // 5
return result;
});
cfy_example(function(x) { console.log(x) }); // 5
```
If the last argument is not a function, a promise will be returned instead:
```javascript
cfy_example().then(function(x) { console.log(x) }); // 5
```
`cfy_node` creates a nodeback-style function from a generator
```javascript
var cfy_node_example = cfy_node(function*() {
var result = yield Promise.resolve(5); // 5
return result;
});
cfy_node_example(function(err, x) { console.log(x) }); // 5
```
If the last argument is not a function, a promise will be returned instead:
```javascript
cfy_node_example().then(function(x) { console.log(x) });
```
`yfy` transforms a callback-style function into a promise which can be yielded within a generator.
```javascript
function add_async(x, y, callback) {
setTimeout(function() {
callback(x + y);
}, 1000);
}
var yfy_example_with_arguments = cfy(function*(a, b) {
var result = yield yfy(add_async)(5, 1); // 6
return result + a + b;
});
yfy_example_with_arguments(2, 7, function(x) { console.log(x) }); // 15
```
`yfy_node` transforms a nodeback-style function into a promise which can be yielded within a generator.
```javascript
function add_async_node(x, y, nodeback) {
setTimeout(function() {
nodeback(null, x + 1);
}, 1000);
}
var yfy_node_example_with_arguments = cfy_node(function*(a, b) {
var result = yield yfy_node(add_async_node)(5, 1); // 6
return result + a + b;
});
yfy_node_example_with_arguments(2, 7, function(err, x) { console.log(x) }); // 15
```
`ycall` is a shorthand that calls `yfy` on a callback-based function and calls it with the remaining parameters. So `ycall(func, x, y)` is equivalent to `yfy(func)(x, y)`
```javascript
function add_async(x, y, callback) {
setTimeout(function() {
callback(x + y);
}, 1000);
}
var ycall_example_with_arguments = cfy(function*(a, b) {
var result = yield ycall(add_async, 5, 1); // 6
return result + a + b;
});
ycall_example_with_arguments(2, 7, function(x) { console.log(x) }); // 15
```
`ycall_node` is a shorthand that calls `yfy_node` on a nodeback-based function and calls it with the remaining parameters. So `ycall_node(func, x, y)` is equivalent to `yfy_node(func)(x, y)`
```javascript
function add_async_node(x, y, nodeback) {
setTimeout(function() {
nodeback(null, x + 1);
}, 1000);
}
var ycall_node_example_with_arguments = cfy_node(function*(a, b) {
var result = yield ycall_node(add_async_node, 5, 1); // 6
return result + a + b;
});
ycall_node_example_with_arguments(2, 7, function(err, x) { console.log(x) }); // 15
```
You will find more examples in [`example.js`](https://github.com/gkovacs/ycall/blob/master/example.js) (for interop with normal callback-based async functions) and [`example_node.js`](https://github.com/gkovacs/ycall/blob/master/example_node.js) (for interop with node-style nodeback-based async functions). The unit tests include examples of usage from Livescript.
By [Geza Kovacs](https://github.com/gkovacs)