async-deco
Advanced tools
Comparing version 9.0.0 to 9.1.0
@@ -16,4 +16,7 @@ "use strict"; | ||
const always = () => true; | ||
function getCacheDecorator(opts = {}) { | ||
const cacheObj = opts.cache || new _memoizeCache.CacheRAM(opts); | ||
const doCacheIf = opts.doCacheIf || always; | ||
return function cache(func) { | ||
@@ -47,2 +50,7 @@ if (typeof func !== 'function') throw new Error('cache: should decorate a function'); | ||
func.apply(context, args).then(res => { | ||
if (!doCacheIf(res)) { | ||
resolve(res); | ||
return; | ||
} | ||
const key = cacheObj.push(args, res); | ||
@@ -49,0 +57,0 @@ |
@@ -16,2 +16,4 @@ "use strict"; | ||
const always = () => true; | ||
function getFallbackCacheDecorator(opts = {}) { | ||
@@ -21,2 +23,3 @@ const cache = opts.cache || new _memoizeCache.CacheRAM(opts); | ||
const noPush = !!opts.noPush; | ||
const doCacheIf = opts.doCacheIf || always; | ||
return function fallbackCache(func) { | ||
@@ -29,3 +32,3 @@ if (typeof func !== 'function') throw new Error('fallbackCache: should decorate a function'); | ||
return func.apply(context, args).then(res => { | ||
if (!noPush) { | ||
if (!noPush && doCacheIf(res)) { | ||
const key = cache.push(args, res); | ||
@@ -32,0 +35,0 @@ |
@@ -16,2 +16,4 @@ "use strict"; | ||
const always = () => true; | ||
function getRetryDecorator(opts = {}) { | ||
@@ -21,2 +23,3 @@ const times = opts.times || Infinity; | ||
const intervalFunc = typeof interval === 'function' ? interval : () => interval; | ||
const doRetryIf = opts.doRetryIf || always; | ||
return function retry(func) { | ||
@@ -34,3 +37,5 @@ if (typeof func !== 'function') throw new Error('retry: should decorate a function'); | ||
customSetTimeout(() => func.apply(context, args).then(resolve).catch(err => { | ||
if (counter < times) { | ||
if (!doRetryIf(err) || counter >= times) { | ||
return reject(err); | ||
} else { | ||
logger('retry', { | ||
@@ -41,4 +46,2 @@ times: counter, | ||
return retry(); | ||
} else { | ||
reject(err); | ||
} | ||
@@ -45,0 +48,0 @@ }), interval); |
@@ -22,5 +22,10 @@ "use strict"; | ||
var always = function always() { | ||
return true; | ||
}; | ||
function getCacheDecorator() { | ||
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var cacheObj = opts.cache || new _memoizeCache.CacheRAM(opts); | ||
var doCacheIf = opts.doCacheIf || always; | ||
return function cache(func) { | ||
@@ -58,2 +63,7 @@ if (typeof func !== 'function') throw new Error('cache: should decorate a function'); | ||
func.apply(context, args).then(function (res) { | ||
if (!doCacheIf(res)) { | ||
resolve(res); | ||
return; | ||
} | ||
var key = cacheObj.push(args, res); | ||
@@ -60,0 +70,0 @@ |
@@ -22,2 +22,6 @@ "use strict"; | ||
var always = function always() { | ||
return true; | ||
}; | ||
function getFallbackCacheDecorator() { | ||
@@ -28,2 +32,3 @@ var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var noPush = !!opts.noPush; | ||
var doCacheIf = opts.doCacheIf || always; | ||
return function fallbackCache(func) { | ||
@@ -40,3 +45,3 @@ if (typeof func !== 'function') throw new Error('fallbackCache: should decorate a function'); | ||
return func.apply(context, args).then(function (res) { | ||
if (!noPush) { | ||
if (!noPush && doCacheIf(res)) { | ||
var key = cache.push(args, res); | ||
@@ -43,0 +48,0 @@ |
@@ -24,2 +24,6 @@ "use strict"; | ||
var always = function always() { | ||
return true; | ||
}; | ||
function getRetryDecorator() { | ||
@@ -32,2 +36,3 @@ var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
}; | ||
var doRetryIf = opts.doRetryIf || always; | ||
return function retry(func) { | ||
@@ -50,3 +55,5 @@ if (typeof func !== 'function') throw new Error('retry: should decorate a function'); | ||
return func.apply(context, args).then(resolve).catch(function (err) { | ||
if (counter < times) { | ||
if (!doRetryIf(err) || counter >= times) { | ||
return reject(err); | ||
} else { | ||
logger('retry', { | ||
@@ -57,4 +64,2 @@ times: counter, | ||
return retry(); | ||
} else { | ||
reject(err); | ||
} | ||
@@ -61,0 +66,0 @@ }); |
{ | ||
"name": "async-deco", | ||
"version": "9.0.0", | ||
"version": "9.1.0", | ||
"description": "A collection of decorators for adding features to asynchronous functions", | ||
@@ -5,0 +5,0 @@ "main": "es5/index", |
@@ -21,2 +21,3 @@ # async-deco | ||
* [log](#log) | ||
* [memoize](#memoize) | ||
* [onFulfilled](#onfulfilled) | ||
@@ -294,2 +295,3 @@ * [onRejected](#onrejected) | ||
* getTags: a function that returns an array of tags. You can use that for purging a set of items from the cache (see the purgeCache decorator). To use this option you should pass the cache object rather than rely on the default (see the section below). | ||
* doCacheIf: a function that takes the result of the function and returns true if we want to cache the result. By default it always returns true. | ||
@@ -402,2 +404,3 @@ #### Use a specific cache engine | ||
* noPush: it true it won't put anything in the cache [optional, defaults to false] | ||
* doCacheIf: a function that takes the result of the function and returns true if we want to cache the result. By default it always returns true. | ||
@@ -507,2 +510,19 @@ For example: | ||
## memoize | ||
The decorated function is executed only when used with a new set of arguments. Then the results are cached and reused. | ||
The result is cached against the arguments. They are checked by reference (strict equality). Promise rejections are cached as well. | ||
The decorator uses a LRU cache algorithm to decide whether to get rid of a cached value. It also supports a time-to-live for cached values. But you have to consider stale cache entries are not removed until the size of the cache exceeds the length. This allows to keep the running time of the algorithm constant (O(1)) for any operation. The cache is local to the process. So multiple process will store multiple cache items. | ||
The decorator factory takes 2 arguments: | ||
* len: the number of items in the cache, default Infinity | ||
* ttl: time to live in ms (default Infinity) | ||
```js | ||
import { memoize } from 'async-deco'; | ||
const memoizeDecorator = memoize({ len: 10, ttl: 10000 }) | ||
memoizeDecorator(() => ...) | ||
``` | ||
The decorator doesn't provide logging. | ||
## onFulfilled | ||
@@ -590,2 +610,3 @@ It executes this function on the result once it is fulfilled. | ||
* interval: how long to wait before running the function again. It can be a number of milliseconds or a function returning a number of milliseconds (the function takes the current attempt as argument) [optional, it defaults to 0] | ||
* doRetryIf: a function that takes as argument the error returned by the decorated function. If it returns true, it will trigger the retry. By default it always returns true. | ||
@@ -592,0 +613,0 @@ #### logs |
@@ -10,6 +10,18 @@ /* eslint-env node, mocha */ | ||
beforeEach(() => { | ||
const cache = new CacheRAM({ getKey: (a, b, c) => a + b + c }) | ||
const cache = new CacheRAM({ getKey: (a) => a }) | ||
cached = cacheDecorator({ cache }) | ||
}) | ||
it('must not cache', (done) => { | ||
const f = cached((a, b, c) => new Promise((resolve, reject) => resolve(a + b + c))) | ||
f(1, 2, 3).then((dep) => { | ||
assert.equal(dep, 6) | ||
f(2, 5, 6).then((dep) => { | ||
assert.equal(dep, 13) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('must cache using different keys', (done) => { | ||
@@ -20,3 +32,3 @@ const f = cached((a, b, c) => new Promise((resolve, reject) => resolve(a + b + c))) | ||
assert.equal(dep, 6) | ||
f(3, 2, 1).then((dep) => { | ||
f(1, 2, 10).then((dep) => { | ||
assert.equal(dep, 6) | ||
@@ -28,2 +40,16 @@ done() | ||
it('does not cache when option is used', (done) => { | ||
const cache2 = new CacheRAM({ getKey: (a, b, c) => a + b + c }) | ||
const cached2 = cacheDecorator({ cache2, doCacheIf: (res) => res !== 6 }) | ||
const f = cached2((a, b, c) => new Promise((resolve, reject) => resolve(a + b + c))) | ||
f(1, 2, 3).then((dep) => { | ||
assert.equal(dep, 6) | ||
f(1, 2, 10).then((dep) => { | ||
assert.equal(dep, 13) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('changes the name of the function', () => { | ||
@@ -30,0 +56,0 @@ const func = cached(function func () {}) |
@@ -36,2 +36,27 @@ /* eslint-env node, mocha */ | ||
it('must not save cache when specified', (done) => { | ||
const cache2 = new CacheRAM() | ||
const cached2 = fallbackCacheDecorator({ cache2, doCacheIf: (res) => res !== 6 }) | ||
let counter = 0 | ||
const f = cached2((a, b, c) => { | ||
return new Promise((resolve, reject) => { | ||
counter++ | ||
if (counter === 1) { | ||
resolve(a + b + c) | ||
} else { | ||
reject(new Error('error')) | ||
} | ||
}) | ||
}) | ||
f(1, 2, 3).then((dep) => { | ||
assert.equal(dep, 6) | ||
f(1, 2, 3).catch((err) => { | ||
assert.equal(err.message, 'error') | ||
assert.instanceOf(err, Error) | ||
done() | ||
}) | ||
}) | ||
}) | ||
it('can\'t fallback using a cached value', (done) => { | ||
@@ -38,0 +63,0 @@ const f = cached((a, b, c) => { |
@@ -8,4 +8,6 @@ /* eslint-env node, mocha */ | ||
let retryForever | ||
let neverRetry | ||
beforeEach(() => { | ||
neverRetry = retryDecorator({ times: 10, doRetryIf: (err) => !(err instanceof Error) }) | ||
retryTenTimes = retryDecorator({ times: 10 }) | ||
@@ -67,2 +69,21 @@ retryForever = retryDecorator() | ||
it('must not retry', (done) => { | ||
let c = 0 | ||
const func = neverRetry(() => { | ||
return new Promise((resolve, reject) => { | ||
c++ | ||
if (c === 5) { | ||
return resolve('done') | ||
} | ||
reject(new Error('error')) | ||
}) | ||
}) | ||
func().catch(function (err) { | ||
assert.equal(err.message, 'error') | ||
assert.equal(c, 1) | ||
done() | ||
}) | ||
}) | ||
it('must retry forever', (done) => { | ||
@@ -69,0 +90,0 @@ let c = 0 |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
191760
114
4584
675
0