# undertake

> Another choice beyond co.

Latest version **0.1.0** (published 2019-03-31) · MIT license · 0 weekly downloads

## Install

```sh
npm install undertake
pnpm add undertake
yarn add undertake
bun add undertake
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.1.0 |
| Published | 2019-03-31 |
| First published | 2018-04-10 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 24.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | YounGoat |
| Maintainers | youngoat |
| Keywords | async, promise, cocurrent, synchronise, generator, coroutine |

## Links

- npm: https://www.npmjs.com/package/undertake
- Repository: https://github.com/YounGoat/ecmascript.undertake
- Issues: https://github.com/YounGoat/ecmascript.undertake/issues
- npm.io page: https://npm.io/package/undertake

## Alternatives

- [@commercetools/sync-actions](https://npm.io/package/@commercetools/sync-actions.md) — 25.1K weekly downloads
- [cwait](https://npm.io/package/cwait.md) — 21.4K weekly downloads
- [@ledgerhq/hw-app-cosmos](https://npm.io/package/@ledgerhq/hw-app-cosmos.md) — 4.2K weekly downloads
- [@financial-times/o-loading](https://npm.io/package/@financial-times/o-loading.md) — 2.8K weekly downloads
- [fa](https://npm.io/package/fa.md) — 185 weekly downloads

## Recent versions

- 0.1.0 (latest) — 2019-03-31
- 0.0.4 — 2018-11-08
- 0.0.3 — 2018-09-16
- 0.0.2 — 2018-08-15
- 0.0.1 — 2018-04-10

## README

#	undertake
__Another choice beyond co.__

[![total downloads of undertake](https://img.shields.io/npm/dt/undertake.svg)](https://www.npmjs.com/package/undertake)
[![undertake's License](https://img.shields.io/npm/l/undertake.svg)](https://www.npmjs.com/package/undertake)
[![latest version of undertake](https://img.shields.io/npm/v/undertake.svg)](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)

---
_Source: https://npm.io/package/undertake · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
