undertake
Version:
Another choice beyond co.
212 lines (158 loc) • 7.48 kB
Markdown
# undertake
__Another choice beyond co.__
[](https://www.npmjs.com/package/undertake)
[](https://www.npmjs.com/package/undertake)
[](https://www.npmjs.com/package/undertake)
> If links in this document not avaiable, please access [README on GitHub](./README.md) directly.
## Description
__undertake__ is incubated from [jinang/co](https://www.npmjs.com/package/jinang). It is something like well-known [co](https://www.npmjs.com/package/co). It just offers another choice.
## Table of Contents
* [Get Started](#get-started)
* [API](#api)
* [undertake vs. undertake.easy](#undertake-vs-undertakeeasy)
* [Links](#links)
## Get Started
```javascript
const undertake = require('undertake');
// A generator function.
function* success() {
// yield promise.
let a = yield Promise.resolve('A');
// yield thunkified function.
let b = yield callback => {
setTimeout(() => callback(null, 'B'), 100);
};
let c = yield subtask(1);
// c equals 3
// Traverse an array.
let d = 0;
yield undertake.each([1,2,3], function*(num, index) {
d += yield Promise.resolve(num);
});
// d equals 6
// Traverse an array and return a mapped one.
let e = yield undertake.map([1,2,3], function*(num, index) {
return yield Promise.resolve(num * 2);
});
// e equals [2,4,6]
let F = function(num_1, num_2, callback) {
setTimeout(() => callback(null, num_1 * num_2), 100);
};
let f1 = yield undertake.calling(F, null, 4, 6);
// f1 equals 24
let f2 = yield undertake.applying(F, null, [ 4, 6 ]);
// f2 equals 24
return a + b + c + d;
}
function* subtask(n) {
let m = yield Promise.resolve(n);
let n = yield Promise.resolve(n+1);
return m + n;
}
// When no callback passed in, an instance of Promise will be returned.
undertake(success).then(ret => {
// ret equals "AB36"
});
// A triditional callback is acceptable.
undertake(success, function(err, data) {
// err equals null
// data euqals "AB36"
});
// RETURN undefined
// If callback is also a generator function, an instance of Promise will be returned.
undertake(success, function*(err, data) {
let f = yield subtask(4);
return data + f;
}).then(ret => {
// ret equals "AB369";
});
// Create a new function which will accept the same paramenters as the generator function do,
// and return an instance of Promise on being invoked.
let fn = undertake.sync(subtask);
fn(2).then(ret => {
// ret equals 5
});
```
## API
* Promise __undertake__(GeneratorFunction *fn*)
Something like `co`.
* Promise __undertake__(GeneratorFunction *fn* [, GeneratorFunction *callback*, boolean *compatible* ])
Successively execute generator functions *fn* and *callback*.
If *compatible* is `true`, returned value which is instance of `Error` will be regarded as normal value. Otherwise and by default, such returned value will trigger rejection.
* void __undertake__(GeneratorFunction *fn*, Function *callback* [, boolean *compatible* ])
Execute the generator function *fn*, then invoke *callback*.
* Promise __undertake.applying__(Function *fn*, Object *this_value*, Array *args*)
Invoke *fn* and return an instance of `Promise`.
Function *fn* SHOULD accept a standard callback function as the last argument. Developer SHOULD NOT put a callback in *args*, it will be automatically appended when *fn* is really invoked.
This util is designed to make things easy to __yield__ a traditional asynchronised function.
* Promise __undertake.calling__(Function *fn*, Object *this_value*, Any *arg_0*, ...)
Invoke *fn* and return an instance of `Promise`.
* Promise __undertake.easy__(GeneratorFunction *fn*)
See [undertake vs. undertake.easy](#undertake-vs-undertake.easy).
* Promise(undefined) __undertake.each__(Array *arr*, GeneratorFunction *iterator*)
For each item of *arr*, execute the generator function *iterator* with the item as the only argument.
* Promise(Array) __undertake.map__(Array *arr*, GeneratorFunction *iterator*)
Return an array of `Promise` instances. Each promise will carry the data returned by the corresponding generator function.
* boolean __undertake.isGenerator__(any *foo*)
A util function.
* boolean __undertake.isGeneratorFunction__(any *foo*)
A util function.
* Function __undertake.sync__(GeneratorFunction *fn* [, Function *callback*])
Wrap a generator function. Without *callback*, the new function will return an instance of `Promise` on being invoked. Otherwise, `callback()` will be invoked finally when the new function is invoked and completed.
* Function __undertake.async__(GeneratorFunction *fn* [, number *callbackIndex*])
Wrap a generator function. The new function will return an instance of `Promise` on being invoked without a callback function, or `callback()` will be invoked finally. Parameter `callbackIndex` will indicate the position of `callback`. By default, the last argument with type of `'function'` will be regarded as the callback function.
If `callback(err, data)` exists, what returned by the generator function will become *data* and what throwed will become *err*.
## undertake vs. undertake.easy
For `undertake`, operator `yield` expects a *promise*, *generator function* or *thunkify function*. If something following `yield` is not expected, an error will be thrown.
For `undertake.easy`, anything is allowed to follow `yield` operator. If it is not an instance of `Promise` or `Function`, itself will be returned by `yield`. E.g.
```javascript
// A generator function.
function* main() {
let a = yield Promise.resolve('A');
// `a` now equals 'A'.
let b = yield 'B';
// `b` now equals 'B';
return a + b;
}
// Error: operator `yield` expects a promise, generator function or thunkify function
let p0 = undertake(main);
// It's OK.
let p1 = undertake.easy(main);
// It's OK. As same as p1.
let p2 = undertake(main, null, true);
```
## undertake.sync vs. undertake.async
`undertake.sync()` and `undertake.async()` are used to create (or so-called "wrap") a generator function and return a new normal one. They two are actually identical when no "callback()" occurs.
```javascript
function* main() {
return yield Promise.resolve('A');
}
function callback(err, data) {
console.log(data.toLowerCase());
}
// A new function is created. "main()" does not run now.
const f0 = undertake.sync(main);
// Promise(A) returned.
f0();
// Promise(A) returned. "callback" is ignored.
f0(callback);
// Both "main()" and "callback()" do not run now.
const f1 = undertake.sync(main, callback);
// Nothing returned. "a" is printed.
f1();
// f2 is the same as f0.
const f2 = undertake.async(main);
// Promise(A) returned.
f2();
// Nothing returned. "a" is printed. Here, the last argument is regarded as "callback" if it is a function.
f2(callback);
// The first (index 0) argument passed to f3 will be regarded as "callback".
const f3 = undertake.async(main, 0);
// Promise(A) returned.
f3();
// Nothing returned. "a" is printed.
f3(callback);
```
## Links
* [CHANGE LOG](./CHANGELOG.md)
* [Homepage](https://github.com/YounGoat/ecmascript.undertake)