Comparing version 0.1.0 to 1.0.0
49
index.js
@@ -1,15 +0,36 @@ | ||
module.exports = function (fn /*, args... */) { | ||
var cache = {/* arg: result */} | ||
var has = Object.prototype.hasOwnProperty | ||
module.exports = function (opts, fn /*, args... */) { | ||
var args = [].slice.call(arguments, 2) | ||
if (typeof opts === 'function') { | ||
if (arguments.length >= 2) args.unshift(fn) | ||
fn = opts | ||
opts = {} | ||
} | ||
var cache = | ||
opts.cache === false ? null : | ||
opts.cache === true || opts.cache == null ? new Storage() : | ||
opts.cache | ||
var callbacks = {/* arg: [callback] */} | ||
var args = [].slice.call(arguments, 1) | ||
return function (arg, cb) { | ||
if (arg in cache) | ||
return cb.call(this, null, cache[arg]) | ||
if (arg in callbacks) | ||
if (cache && cache.has(arg)) { | ||
var self = this | ||
return process.nextTick(function () { | ||
if (cache.has(arg)) | ||
cb.call(self, null, cache.get(arg)) | ||
else | ||
run.call(self, arg, cb) | ||
}) | ||
} | ||
run.call(this, arg, cb) | ||
} | ||
function run(arg, cb) { | ||
if (has.call(callbacks, arg)) | ||
return callbacks[arg].push([this, cb]) | ||
var cbs = callbacks[arg] = [[this, cb]] | ||
fn.apply(this, args.concat(arg, function (err, result) { | ||
if (!err) | ||
cache[arg] = result | ||
if (!err && cache) | ||
cache.set(arg, result) | ||
while (cbs.length) { | ||
@@ -24,1 +45,13 @@ cb = cbs.shift() | ||
function Storage() { | ||
this.data = {} | ||
} | ||
Storage.prototype.has = function (key) { | ||
return has.call(this.data, key) | ||
} | ||
Storage.prototype.get = function (key) { | ||
return this.data[key] | ||
} | ||
Storage.prototype.set = function (key, value) { | ||
this.data[key] = value | ||
} |
{ | ||
"name": "asyncmemo", | ||
"version": "0.1.0", | ||
"version": "1.0.0", | ||
"description": "memoize asynchronous function calls", | ||
@@ -25,4 +25,4 @@ "main": "index.js", | ||
"devDependencies": { | ||
"tape": "^4.5.0" | ||
"tape": "^4.6.2" | ||
} | ||
} |
# asyncmemo | ||
memoize asynchronous function calls | ||
Memoize asynchronous function calls. Combine multiple calls with the same | ||
argument so that the underlying function is only called once for that argument. | ||
Optionally cache the result for that argument. | ||
@@ -11,10 +13,27 @@ ## Install | ||
## Usage | ||
## Example | ||
```js | ||
var asyncMemo = require('asyncmemo') | ||
var cache = asyncMemo(fn, [args...]) | ||
cache(val, cb) | ||
var xhr = require('xhr') | ||
var get = asyncMemo(function (base, path, cb) { | ||
xhr.get(base + path, cb) | ||
}, 'http://localhost') | ||
get('/foo', function (err, resp) { | ||
console.log(err, resp) | ||
}) | ||
``` | ||
## API | ||
### `asyncMemo([opts,] fn, [args...]): memo` | ||
- `opts.cache`: cache object, or false to disable cache | ||
- `fn([args...], arg, cb(err, result))`: the asyncronous function to memoize | ||
- `args`: arguments to prepend to each call to `fn` | ||
- `memo(arg, cb(err, result))`: memoized asynchronous function | ||
A custom cache object can be passed using the `cache` option. This should have | ||
`has`, `get`, and `set` methods. | ||
## Related | ||
@@ -26,2 +45,4 @@ | ||
- [memoizeasync](https://www.npmjs.com/package/memoizeasync) | ||
- [thunky](https://github.com/mafintosh/thunky) - does the same except memoizes | ||
only one value | ||
@@ -28,0 +49,0 @@ ## License |
21
test.js
@@ -94,1 +94,22 @@ var asyncMemo = require('.') | ||
}) | ||
test('without cache', function (t) { | ||
t.plan(4) | ||
var run = asyncMemo({cache: false}, function (arg, cb) { | ||
setImmediate(function () { | ||
t.pass('called') | ||
cb(null, arg) | ||
}) | ||
}) | ||
run('a', function () { | ||
t.pass('one') | ||
setImmediate(function () { | ||
run('a', function () { | ||
t.pass('two') | ||
}) | ||
}) | ||
}) | ||
}) |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
18185
5
150
1
56