Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

async-deco

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

async-deco - npm Package Compare versions

Comparing version 4.3.0 to 5.0.0

tests/utils/parallel.spec.js

4

callback/cache.js
var _cache = require('../src/cache');
var wrapper = require('../src/noop');
function cache(cache) {
return _cache(wrapper, cache);
function cache(cache, opts) {
return _cache(wrapper, cache, opts);
}
module.exports = cache;
var _fallbackCache = require('../src/fallback-cache');
var wrapper = require('../src/noop');
function fallbackCache(cache, error) {
return _fallbackCache(wrapper, cache, error);
function fallbackCache(cache, opts) {
return _fallbackCache(wrapper, cache, opts);
}
module.exports = fallbackCache;
{
"name": "async-deco",
"version": "4.3.0",
"version": "5.0.0",
"description": "A collection of decorators for adding features to asynchronous functions (callback or promise based).",

@@ -28,3 +28,3 @@ "main": "index.js",

"husky": "^0.10.2",
"memoize-cache": "^1.0.2",
"memoize-cache": "^3.0.0",
"mocha": "^2.1.0",

@@ -36,4 +36,5 @@ "npm-release": "^1.0.0"

"require-all": "^2.0.0",
"setimmediate": "^1.0.4"
"setimmediate": "^1.0.4",
"uuid": "^2.0.2"
}
}
var _cache = require('../src/cache');
var wrapper = require('../src/promise-translator');
function cache(cache) {
return _cache(wrapper, cache);
function cache(cache, opts) {
return _cache(wrapper, cache, opts);
}
module.exports = cache;
var _fallbackCache = require('../src/fallback-cache');
var wrapper = require('../src/promise-translator');
function fallbackCache(cache, error) {
return _fallbackCache(wrapper, cache, error);
function fallbackCache(cache, opts) {
return _fallbackCache(wrapper, cache, opts);
}
module.exports = fallbackCache;

@@ -157,3 +157,3 @@ async-deco

It logs "cachehit" with {key: cache key, result: cache result}
It logs "memoize-hit" with {key: cache key, result: cache result}

@@ -169,6 +169,7 @@ Cache

```
It takes 1 argument:
It takes 2 arguments:
* a cache object [mandatory]. The interface should be compatible with memoize-cache (https://github.com/sithmel/memoize-cache)
* an "options" object [optional]:
It logs "cachehit" with {key: cache key, result: cache result}.
It logs "cache-hit" with {key: cache key, result: cache result} or "cache-error" (when the cache fails) with {cacheErr: error object from the cache}.

@@ -191,3 +192,3 @@ Proxy

It logs "access denied" with { err: error returned by the guard function}
It logs "proxy-denied" with { err: error returned by the guard function}

@@ -232,3 +233,3 @@ Fallback

var fallback = fallbackCacheDecorator(cache, Error);
var fallback = fallbackCacheDecorator(cache, options);
var myfunc = fallback(function (..., cb) { .... });

@@ -238,5 +239,8 @@ ```

* a cache object [mandatory]. The interface should be compatible with memoize-cache (https://github.com/sithmel/memoize-cache)
* error instance for deciding to fallback, or a function taking the error and result (if it returns true it'll trigger the fallback) [optional, it falls back on any error by default]
* an options object with this optional attributes:
* error: the error instance for deciding to fallback, or a function taking the error and result (if it returns true it'll trigger the fallback) [optional, it falls back on any error by default]
* useStale: if true it will use "stale" cache items as valid [optional, defaults to false]
* noPush: it true it won't put anything in the cache [optional, defaults to false]
It logs "fallback-cache" with {key: cache key, result: cache result, actualResult: {err: error returned, res: result returned}}
It logs "fallback-cache-hit" with {key: cache key, result: cache object, actualResult: {err: error returned, res: result returned}} or "fallback-cache-error" with {err: error returned by the function, cacheErr: error returned by the cache}.

@@ -303,3 +307,3 @@ Timeout

It logs "deduping" whenever is calling more than one callback with the same results.
It logs "dedupe" whenever is calling more than one callback with the same results.
{len: number of function call saved, key: cache key}

@@ -326,7 +330,7 @@

---------------------
This special decorator add a couple of important checks to your callback based asynchronous function.
It capture any unhandled exception that has been throwed and it uses as "err" argument of the callback.
If the callback is fired twice, the second time it will be fire a "Callback fired twice" exception.
This special decorator adds a couple of important checks to your callback based asynchronous functions.
It captures any unhandled exception that has been throwed, and it uses it as "err" argument of the callback.
If the callback is fired twice, the second time it will fire a "Callback fired twice" exception.
```js
var callbackify = require('async-deco/utils/sanitizeAsyncFunction');
var sanitizeAsyncFunction = require('async-deco/utils/sanitizeAsyncFunction');

@@ -410,2 +414,63 @@ var func = sanitizeAsyncFunction(function () {

Parallel - Waterfall - Race
---------------------------
These special utilities can be used to manage the execution of a group of functions (callback based).
"parallel" executes every function in parallel. If a function returns an error the execution stops immediatly returning the error.
The functions will get the same arguments and the result will be an array of all the results.
```js
var func = parallel([
function (x, cb) {
cb(null, x + 1);
},
function (x, cb) {
cb(null, x + 2);
}
]);
func(3, function (err, values) {
// values contains [4, 5]
});
```
"waterfall" executes the functions in series. The first function will get the arguments and the others will use the arguments passed by the previous one:
```js
var func = waterfall([
function (x, cb) {
cb(null, x + ' world');
},
function (x, cb) {
cb(null, x + '!');
}
]);
func('hello', function (err, value) {
// value === 'hello world!'
});
```
"race" will execute all functions in parallel but it will return the first valid result.
It is very easy to combine these functions to create a more complex flow:
```js
var func = waterfall([
parallel([
function (x, cb) {
cb(null, x * 2);
},
function (x, cb) {
cb(null, x * 3);
}
]),
function (numbers, cb) {
cb(null, numbers.reduce(function (acc, item) {
return acc + item;
}, 0));
},
function (x, cb) {
cb(null, x - 5);
}
]);
func(5, function (err, value) {
// value === 20;
});
```
Examples and use cases

@@ -412,0 +477,0 @@ ======================

var defaultLogger = require('../utils/default-logger');
function cacheDecorator(wrapper, cache) {
function cacheDecorator(wrapper, cache, opts) {
opts = opts || {};
return wrapper(function (func) {

@@ -11,14 +13,18 @@ return function () {

args[args.length - 1] = function (err, dep) {
if (!err) {
cache.push(args, dep);
}
cb(undefined, dep);
};
cache.query(args, function (err, cacheQuery) {
if (!err && cacheQuery.cached === true) {
logger('cachehit', {key: cacheQuery.key, result: cacheQuery.hit});
cb(undefined, cacheQuery.hit);
if (err) {
logger('cache-error', {cacheErr: err});
func.apply(context, args);
}
else if (cacheQuery.cached === true && !cacheQuery.stale) {
logger('cache-hit', {key: cacheQuery.key, result: cacheQuery});
cb(null, cacheQuery.hit);
}
else {
args[args.length - 1] = function (err, res) {
if (!err) {
cache.push(args, res);
}
cb(err, res);
};
func.apply(context, args);

@@ -25,0 +31,0 @@ }

var defaultLogger = require('../utils/default-logger');
var keyGetter = require('memoize-cache/key-getter');
function dedupeDecorator(wrapper, getKey) {
getKey = getKey || function () { return '_default'; };
getKey = keyGetter(getKey || function () { return '_default'; });

@@ -14,3 +15,3 @@ return wrapper(function (func) {

var cb = args[args.length - 1];
var cacheKey = getKey.apply(context, args).toString();
var cacheKey = getKey.apply(context, args);

@@ -20,3 +21,3 @@ function runQueue(cacheKey, err, dep) {

if (len > 1) {
logger('deduping', {len: len, key: cacheKey});
logger('dedupe', {len: len, key: cacheKey});
}

@@ -29,3 +30,6 @@ for (var i = 0; i < len; i++) {

if (!(cacheKey in callback_queues)) {
if (cacheKey === null) {
func.apply(context, args);
}
else if (!(cacheKey in callback_queues)) {
// creating callback

@@ -32,0 +36,0 @@ args[args.length - 1] = (function (cacheKey) {

var defaultLogger = require('../utils/default-logger');
function fallbackCacheDecorator(wrapper, cache, error) {
function fallbackCacheDecorator(wrapper, cache, opts) {
var condition;
error = error || Error;
opts = opts || {};
var error = opts.error || Error;
var useStale = opts.useStale;
var noPush = opts.noPush;
if (error === Error || Error.isPrototypeOf(error)) {

@@ -23,6 +27,11 @@ condition = function (err, dep) { return err instanceof error; };

cache.query(args, function (e, cacheQuery) {
if (!e && cacheQuery.cached === true) {
logger('fallback-cachehit', {key: cacheQuery.key, result: cacheQuery.hit, actualResult: {err: err, res: dep}});
cb(undefined, cacheQuery.hit);
if (e) {
logger('fallback-cache-error', {err: err, cacheErr: e});
cb(err, dep);
}
else if (cacheQuery.cached === true &&
(!cacheQuery.stale || (useStale && cacheQuery.stale))) {
logger('fallback-cache-hit', {key: cacheQuery.key, result: cacheQuery, actualResult: {err: err, res: dep}});
cb(null, cacheQuery.hit);
}
else {

@@ -34,4 +43,4 @@ cb(err, dep);

else {
cache.push(args, dep);
cb(undefined, dep);
!noPush && cache.push(args, dep);
cb(null, dep);
}

@@ -38,0 +47,0 @@ };

@@ -22,3 +22,3 @@ var defaultLogger = require('../utils/default-logger');

logger('fallback', {actualResult: {err: err, res: dep}});
cb(undefined, fallbackValue);
cb(null, fallbackValue);
}

@@ -25,0 +25,0 @@ else {

require('setimmediate');
var defaultLogger = require('../utils/default-logger');
var keyGetter = require('memoize-cache/key-getter');
function limitDecorator(wrapper, max, getKey) {
getKey = getKey || function () { return '_default'; };
getKey = keyGetter(getKey || function () { return '_default'; });

@@ -16,3 +17,3 @@ return wrapper(function (func) {

var cb = args[args.length - 1];
var cacheKey = getKey.apply(context, args).toString();
var cacheKey = getKey.apply(context, args);

@@ -19,0 +20,0 @@ function runQueues() {

var buildLogger = require('../utils/build-logger');
var defaultLogger = require('../utils/default-logger');
var uuid = require('uuid');

@@ -10,3 +11,3 @@ function logDecorator(wrapper, log, name) {

if (log) {
id = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);
id = uuid.v4();
context = buildLogger(this, name, id, log);

@@ -22,3 +23,3 @@ } else {

if (err) {
logger('error', {
logger('log-error', {
err: err

@@ -28,3 +29,3 @@ });

else {
logger('end', {
logger('log-end', {
result: dep

@@ -35,3 +36,3 @@ });

};
logger('start');
logger('log-start', {args: args.slice(0, -1), context: context});
func.apply(context, args);

@@ -38,0 +39,0 @@ };

var defaultLogger = require('../utils/default-logger');
var keyGetter = require('memoize-cache/key-getter');
function memoizeDecorator(wrapper, getKey) {
getKey = getKey || function () { return '_default'; };
getKey = keyGetter(getKey || function () { return '_default'; });
return wrapper(function (func) {

@@ -12,5 +13,5 @@ var cache = {};

var cb = args[args.length - 1];
var cacheKey = getKey.apply(context, args).toString();
var cacheKey = getKey.apply(context, args);
args[args.length - 1] = function (err, dep) {
if (!err) {
if (!err && cacheKey !== null) {
cache[cacheKey] = dep;

@@ -20,5 +21,5 @@ }

};
if (cacheKey in cache) {
logger('cachehit', {key: cacheKey, result: cache[cacheKey]});
return cb(undefined, cache[cacheKey]);
if (cacheKey !== null && cacheKey in cache) {
logger('memoize-hit', {key: cacheKey, result: cache[cacheKey]});
return cb(null, cache[cacheKey]);
}

@@ -25,0 +26,0 @@ else {

@@ -14,3 +14,3 @@ var defaultLogger = require('../utils/default-logger');

if (err) {
logger('access denied', {
logger('proxy-denied', {
err: err

@@ -17,0 +17,0 @@ });

@@ -10,2 +10,3 @@ var assert = require('chai').assert;

dedupeKey = dedupeDecorator(function (n) { return n % 2 === 0 ? 'even' : 'odd'; });
noDedupe = dedupeDecorator(function (n) { return null; });
});

@@ -100,2 +101,46 @@

});
it('must dedupe a function using a key', function (done) {
var numberRuns = 0;
var numberCBRuns = 0;
var f = noDedupe(function (a, next) {
numberRuns++;
setTimeout(function () {
next(undefined, a);
}, 0);
});
f(1, function (err, res) {
numberCBRuns++;
assert.equal(res, 1);
});
f(2, function (err, res) {
numberCBRuns++;
assert.equal(res, 2);
});
f(3, function (err, res) {
numberCBRuns++;
assert.equal(res, 3);
});
f(4, function (err, res) {
numberCBRuns++;
assert.equal(res, 4);
});
f(5, function (err, res) {
numberCBRuns++;
assert.equal(res, 5);
});
setTimeout(function () {
assert.equal(numberRuns, 5);
assert.equal(numberCBRuns, 5);
done();
}, 60);
});
});

@@ -24,4 +24,4 @@ var assert = require('chai').assert;

assert.deepEqual(log, [
{type: 'start', obj: undefined},
{type: 'end', obj: {result: 6}}
{type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context}},
{type: 'log-end', obj: {result: 6}}
]);

@@ -39,4 +39,4 @@ done();

assert.deepEqual(log, [
{type: 'start', obj: undefined},
{type: 'error', obj: {err: new Error('error!')}}
{type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context}},
{type: 'log-error', obj: {err: new Error('error!')}}
]);

@@ -43,0 +43,0 @@ done();

@@ -27,4 +27,4 @@ var assert = require('chai').assert;

assert.deepEqual(log, [
{type: 'start', obj: undefined},
{type: 'end', obj: {result: 6}}
{type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context}},
{type: 'log-end', obj: {result: 6}}
]);

@@ -44,4 +44,4 @@ done();

assert.deepEqual(log, [
{type: 'start', obj: undefined},
{type: 'error', obj: {err: new Error('error!')}}
{type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context}},
{type: 'log-error', obj: {err: new Error('error!')}}
]);

@@ -48,0 +48,0 @@ done();

@@ -40,4 +40,4 @@ var assert = require('chai').assert;

assert.deepEqual(log, [
{ type: 'start', obj: undefined },
{ type: 'end', obj: { result: 6 } }
{type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context}},
{ type: 'log-end', obj: { result: 6 } }
]);

@@ -59,3 +59,4 @@ done();

assert.equal(dep, 'no value');
assert.deepEqual(log[0], { type: 'start', obj: undefined });
assert.deepEqual(log[0], { type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context} });
assert.deepEqual(log[1], { type: 'timeout', obj: { ms: 20 }});

@@ -72,3 +73,3 @@

assert.instanceOf(log[4].obj.actualResult.err, TimeoutError);
assert.deepEqual(log[5], { type: 'end', obj: { result: 'no value' } });
assert.deepEqual(log[5], { type: 'log-end', obj: { result: 'no value' } });
done();

@@ -92,3 +93,3 @@ });

assert.equal(dep, 6);
assert.deepEqual(log[0], { type: 'start', obj: undefined });
assert.deepEqual(log[0], { type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context} });
assert.deepEqual(log[1], { type: 'timeout', obj: { ms: 20 }});

@@ -99,3 +100,3 @@ assert.equal(log[2].type, 'retry');

assert.instanceOf(log[2].obj.actualResult.err, TimeoutError);
assert.deepEqual(log[3], { type: 'end', obj: { result: 6 } });
assert.deepEqual(log[3], { type: 'log-end', obj: { result: 6 } });
done();

@@ -102,0 +103,0 @@ });

@@ -62,4 +62,4 @@ var assert = require('chai').assert;

assert.deepEqual(log, [
{ type: 'start', obj: undefined },
{ type: 'end', obj: { result: 6 } }
{ type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context} },
{ type: 'log-end', obj: { result: 6 } }
]);

@@ -79,3 +79,3 @@ done();

assert.equal(dep, 'no value');
assert.deepEqual(log[0], { type: 'start', obj: undefined });
assert.deepEqual(log[0], { type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context} });
assert.deepEqual(log[1], { type: 'timeout', obj: { ms: 20 }});

@@ -92,3 +92,3 @@

assert.instanceOf(log[4].obj.actualResult.err, TimeoutError);
assert.deepEqual(log[5], { type: 'end', obj: { result: 'no value' } });
assert.deepEqual(log[5], { type: 'log-end', obj: { result: 'no value' } });
done();

@@ -111,3 +111,3 @@ });

assert.deepEqual(log[0], { type: 'start', obj: undefined });
assert.deepEqual(log[0], { type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context} });
assert.deepEqual(log[1], { type: 'timeout', obj: { ms: 20 }});

@@ -118,3 +118,3 @@ assert.equal(log[2].type, 'retry');

assert.instanceOf(log[2].obj.actualResult.err, TimeoutError);
assert.deepEqual(log[3], { type: 'end', obj: { result: 6 } });
assert.deepEqual(log[3], { type: 'log-end', obj: { result: 6 } });
done();

@@ -121,0 +121,0 @@ });

@@ -43,4 +43,4 @@ var assert = require('chai').assert;

assert.deepEqual(log, [
{ type: 'start', obj: undefined },
{ type: 'end', obj: { result: 6 } }
{ type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context} },
{ type: 'log-end', obj: { result: 6 } }
]);

@@ -87,4 +87,4 @@ done();

assert.deepEqual(log, [
{ type: 'start', obj: undefined },
{ type: 'end', obj: { result: 6 } }
{ type: 'log-start', obj: {args: [1, 2, 3], context: log[0].obj.context} },
{ type: 'log-end', obj: { result: 6 } }
]);

@@ -91,0 +91,0 @@ done();

@@ -20,3 +20,3 @@ function isPromise(obj) {

output.then(function (res) { // onfulfilled
cb(undefined, res);
cb(null, res);
},

@@ -28,3 +28,3 @@ function (error) { // onrejected

else {
cb(undefined, output);
cb(null, output);
}

@@ -31,0 +31,0 @@ };

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc