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

memoize-fs

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

memoize-fs - npm Package Compare versions

Comparing version 0.0.5 to 0.1.0

gruntfile.js

127

index.js

@@ -30,7 +30,2 @@ 'use strict';

function checkOptions(optExt) {
if (optExt.salt && typeof optExt.salt !== 'string') { throw new Error('salt option of type string expected, got \'' + typeof optExt.salt + '\''); }
if (optExt.cacheId && typeof optExt.cacheId !== 'string') { throw new Error('cacheId option of type string expected, got \'' + typeof optExt.cacheId + '\''); }
}
function getCacheFilePath(fn, args, opt) {

@@ -45,3 +40,3 @@

if (typeof value === 'function') {
return;
return; // ignore arguments and attributes of type function silently
}

@@ -78,2 +73,8 @@ if (typeof value === 'object' && value !== null) {

function memoizeFn(fn, opt) {
function checkOptions(optExt) {
if (optExt.salt && typeof optExt.salt !== 'string') { throw new Error('salt option of type string expected, got \'' + typeof optExt.salt + '\''); }
if (optExt.cacheId && typeof optExt.cacheId !== 'string') { throw new Error('cacheId option of type string expected, got \'' + typeof optExt.cacheId + '\''); }
}
if (opt && typeof opt !== 'object') { throw new Error('opt of type object expected, got \'' + typeof opt + '\''); }

@@ -91,3 +92,9 @@

var memFn = function () {
var args = arguments;
var args = arguments,
fnaCb = _.last(args);
if (typeof fnaCb === 'function' && fnaCb.length > 0) {
optExt.async = true;
}
return new Promise(function (resolve, reject) {

@@ -98,6 +105,2 @@ /* jshint unused: vars */

fs.readFile(filePath, { encoding: 'utf8' }, function (err, data) {
var result,
resultArr,
resultType,
resultStr;

@@ -129,35 +132,83 @@ function stringifyResult(r) {

if (err || optExt.force) {
delete optExt.force;
// result has not been cached yet or needs to be recached - cache and return it!
try {
result = fn.apply(null, args);
} catch (e) {
return reject(e);
}
if (result && result.then) {
// result is a promise instance
return result.then(function (retObj) {
fs.writeFile(filePath, typeof retObj + '\n' + stringifyResult(retObj)); // async without callback!
resolve(retObj);
},
function (err) {
function cacheAndReturn() {
var result,
resultStr;
function processFnAsync() {
var fnaArgs = _.initial(args),
fnaCb = _.last(args);
fnaArgs.push(function(/* err, result... */) {
var cbErr = _.first(arguments),
cbArgs = _.rest(arguments);
if (cbErr) {
// if we have an exception we don't cache anything
reject(err);
});
} else {
resultStr = stringifyResult(result);
fs.writeFile(filePath, typeof result + '\n' + resultStr, function (err) {
if (err) {
reject(err);
} else {
resolve(result);
return reject(cbErr);
}
cbArgs.unshift(null);
fs.writeFile(filePath, 'object' + '\n' + stringifyResult(cbArgs)); // async without callback!
resolve(fnaCb.apply(null, cbArgs));
});
fn.apply(null, fnaArgs);
}
function processFn() {
try {
result = fn.apply(null, args);
} catch (e) {
return reject(e);
}
if (result && result.then && typeof result.then === 'function') {
// result is a promise instance
return result.then(function (retObj) {
fs.writeFile(filePath, typeof retObj + '\n' + stringifyResult(retObj)); // async without callback!
resolve(retObj);
},
function (err) {
// if we have an exception we don't cache anything
reject(err);
});
} else {
resultStr = stringifyResult(result);
fs.writeFile(filePath, typeof result + '\n' + resultStr, function (err) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
}
}
if (optExt.async) {
return processFnAsync();
}
return processFn();
}
function retrieveAndReturn() {
var resultArr = data.split('\n');
function processFnAsync() {
var fnaCb = _.last(args);
resolve(fnaCb.apply(null, parseResult(_.rest(resultArr).join('\n'), _.first(resultArr))));
}
function processFn() {
resolve(parseResult(_.rest(resultArr).join('\n'), _.first(resultArr)));
}
if (optExt.async) {
return processFnAsync();
}
return processFn();
}
if (err || optExt.force) {
delete optExt.force;
// result has not been cached yet or needs to be recached - cache and return it!
cacheAndReturn();
} else {
// result has already been cached - return it!
resultArr = data.split('\n');
resultType = _.first(resultArr);
resolve(parseResult(_.rest(resultArr).join('\n'), resultType));
retrieveAndReturn();
}

@@ -164,0 +215,0 @@ });

{
"name": "memoize-fs",
"version": "0.0.5",
"version": "0.1.0",
"description": "memoize/cache in file system solution for Node.js",

@@ -11,4 +11,7 @@ "author": {

"scripts": {
"test": "mocha --reporter nyan test",
"cover": "rm -rf coverage && ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report html && open coverage/index.html"
"test": "mocha test && grunt",
"mocha": "mocha --reporter nyan test",
"jshint": "grunt",
"istanbul": "rm -rf coverage && ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report html && open coverage/memoize-fs/index.js.html",
"coveralls": "rm -rf coverage && ./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
},

@@ -37,3 +40,6 @@ "homepage": "https://github.com/borisdiakur/memoize-fs",

"coveralls": "~2.10.0",
"mocha-lcov-reporter": "0.0.1"
"mocha-lcov-reporter": "0.0.1",
"grunt": "~0.4.5",
"grunt-contrib-jshint": "~0.10.0",
"grunt-cli": "~0.1.13"
},

@@ -40,0 +46,0 @@ "private": false,

@@ -13,2 +13,3 @@ # memoize-fs

The motivation behind this module is that sometimes you have to persist cached function calls but you do not want to deal with an extra process (ie. managing a Redis store).
Memoization is best technique to save on memory or CPU cycles when we deal with repeated operations. For detailed insight see: http://en.wikipedia.org/wiki/Memoization

@@ -19,3 +20,4 @@

* Works with almost all kind and any length of function arguments – [__custom serialization is posible__](#serialize)
* Support for [__promisified functions__](#memoizing-promisified-functions)
* Supports memoization of [__asynchronous functions__](#memoizing-asynchronous-functions)
* Supports memoization of [__promisified functions__](#memoizing-promisified-functions)
* Cache [__can be invalidated manually__](#manual-cache-invalidation)

@@ -27,3 +29,5 @@

$ npm install memoize-fs
```shell
npm install memoize-fs --save
```

@@ -48,18 +52,31 @@ ## Usage

### Memoizing promisified functions
### Memoizing asynchronous functions
In order to memoize an async function it must be first promisified in the following manner:
memoise-fs assumes a function asynchronous if the last argument it accepts is of type `function` and that function itself accepts at least one argument.
So basically you don't have to do anything differently than when memoizing synchronous functions. Just make sure the above condition is fulfilled.
Here is an example of memoizing a function with a callback:
Before:
```javascript
var funAsync = function (a, b, cb) { setTimeout(function () { cb(null, a + b); }, 100); };
var funAsync = function (a, b, cb) {
setTimeout(function () {
cb(null, a + b);
}, 100);
};
// later
funAsync(1, 2, function (err, result) {
if (err) throw err;
console.log(result);
});
memoize.fn(funAsync).then(function (memFn) {
memFn(1, 2, function (err, sum) { if (err) { throw err; } console.log(sum); }).then(function () {
memFn(1, 2, function (err, sum) { if (err) { throw err; } console.log(sum); }).then(function () { // cache hit
// callback is called with previously cached arguments
}, function (err) { /* handle error */ });
}, function (err) { /* handle error */ });
}, function (err) { /* handle error */ });
```
After:
### Memoizing promisified functions
You can also memoize a promisified function. memoize-fs assumes a function promisified if its result is _thenable_
which means that the result is an object with a property `then` of type `function` (read more about JavaScript promises [here](http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=de)).
So again it's the same as with memoizing synchronous functions.
Here is an example of memoizing a promisified function:
```javascript

@@ -72,11 +89,10 @@ var funPromisified = function (a, b) {

// later
funPromisified(1, 2).then(function (result) {
console.log(result);
}, function (err) {
throw err;
});
// now we can memoize it
memoize.fn(funPromisified).then(...
memoize.fn(funPromisified).then(function (memFn) {
memFn(1, 2).then(function (result) {
assert.strictEqual(result, 3);
memFn(1, 2).then(function (result) { // cache hit
assert.strictEqual(result, 3);
}, function (err) { /* handle error */ });
}, function (err) { /* handle error */ });
}, function (err) { /* handle error */ });
```

@@ -138,3 +154,3 @@

```javascript
memoized.invalidate().then(...
memoize.invalidate().then(...
```

@@ -145,14 +161,44 @@

```javascript
memoized.invalidate('foobar').then(...
memoize.invalidate('foobar').then(...
```
## Common pitfalls
- Be carefull when memoizing a function which uses __variables from the outer scope__.
The value of these variables may change during runtime but the cached result will remain the same
when calling the memoized function with the same arguments as the first time when the result was cached.
- Be careful when memoizing a function which excepts arguments which are of type `function` or have attributes of type `function`.
__These arguments will be ignored silently during serialization__.
To avoid flawy caching please use [__custom serialization__](#serialize).
## Contributing
Issues and Pull-requests welcome. If you want to submit a patch, please make sure that you follow this simple rule:
Issues and Pull-requests are absolutely welcome. If you want to submit a patch, please make sure that you follow this simple rule:
> All code in any code-base should look like a single person typed it, no matter how
many people contributed. —[idiomatic.js](https://github.com/rwldrn/idiomatic.js/)
many people contributed. — [idiomatic.js](https://github.com/rwldrn/idiomatic.js/)
## Change Log
Lint with:
```shell
npm run jshint
```
Test with:
```shell
npm run mocha
```
Check code coverage with:
```shell
npm run istanbul
```
Then please commit with a __detailed__ commit message.
## Change log
v0.1.0 - memoization of [asynchronous functions](#memoizing-asynchronous-functions)
v0.0.5 - coveralls and mocha-lcov-reporter are dev-dependencies

@@ -159,0 +205,0 @@

Sorry, the diff of this file is not supported yet

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