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

nano-memoize

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nano-memoize - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2

76

browser/nano-memoize.js

@@ -10,3 +10,13 @@ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

function nanomemoize (fn, options={}) {
// for sngl argument functions, just use a JS object key look-up
const {
serializer = (value) => JSON.stringify(value),
equals,
maxAge,
maxArgs,
vargs = hsVrgs(fn)
} = options,
s = {}, // single arg function key/value cache
k = [], // multiple arg function arg key cache
v = []; // multiple arg function result cache
// for single argument functions, just use a JS object key look-up
function sngl (f,s,chng,serializer,arg) {

@@ -16,5 +26,5 @@ // strings must be stringified because cache[1] should not equal or overwrite cache["1"] for value = 1 and value = "1"

if(chng) chng(key);
return s[key] || ( s[key] = f.call(this, arg));
return s[key] || (s[key] = f.call(this, arg));
}
// for mltpl arg functions, loop through a cache of all the args
// for multiple arg functions, loop through a cache of all the args
// looking at each arg separately so a test can abort as soon as possible

@@ -38,41 +48,18 @@ function mltpl(f,k,v,eq,chng,max=0,...args) {

const i = rslt.i>=0 ? rslt.i : v.length;
if(chng) { chng(i); }
if(chng) chng(i);
return typeof rslt.v === "undefined" ? v[i] = f.call(this,...(k[i] = args)) : rslt.v;
}
const {
serializer = (value) => JSON.stringify(value),
equals,
maxAge,
maxArgs,
vargs = hsVrgs(fn),
expireInterval = 1
} = options,
s = {}, // sngl arg function key/value cache
k = [], // mltpl arg function arg key cache
v = [], // mltpl arg function result cache
c = {}, // key chng cache
chng = (cache,key) => { // logs key chngs
c[key] = {key,cache};
},
t = {},
tmout = (chng) => { // deletes timed-out keys
if(t[chng.key]) { clearTimeout(t[chng.key]); }
t[chng.key] = setTimeout(() => {
delete chng.cache[chng.key];
delete t[chng.key];
},maxAge);
};
let f,
let m,
unry = fn.length===1 && !equals && !vargs;
// pre-bind core arguments, faster than using a closure or passing on stack or in this case using a partial
if(unry) {
f = sngl.bind(
m = sngl.bind(
this,
fn,
s,
(maxAge ? chng.bind(this,s): null), // turn chng logging on and bind to arg cache s
maxAge ? (key) => setTimeout(() => { delete s[key]; },maxAge) : null,
serializer
);
} else {
f = mltpl.bind(
m = mltpl.bind(
this,

@@ -83,3 +70,3 @@ fn,

equals || ((a,b) => a===b), // default to just a regular strict comparison
(maxAge ? chng.bind(this,v): null), // turn chng logging on and bind to arg cache v
maxAge ? (key) => setTimeout(() => { delete v[key]; },maxAge) : null,
maxArgs

@@ -89,23 +76,12 @@ );

// reset all the caches, must chng array length or delete keys on objects to retain bind integrity
f.clear = () => {
m.clear = () => {
Object.keys(s).forEach((k) => delete s[k]);
k.length = 0; //k.splice(0,k.length);
v.length = 0; //v.splice(0,v.length);
Object.keys(c).forEach(k => delete c[k]);
Object.keys(t).forEach(k => { clearTimeout(t[k]); delete t[k]; });
k.length = 0;
v.length = 0;
};
f.keys = () => (!unry ? k.slice() : null);
f.values = () => (!unry ? v.slice() : null);
f.keyValues = () => (unry ? Object.assign({},s) : null);
if(expireInterval) {
f.interval = setInterval(() => { // process key chngs out of cycle for speed
for(const p in c) {
if(maxAge) { tmout(c[p]); }
delete c[p];
}
},expireInterval);
}
return f;
m.keys = () => (!unry ? k.slice() : null);
m.values = () => (!unry ? v.slice() : null);
m.keyValues = () => (unry ? Object.assign({},s) : null);
return m;
}
if(typeof(module)!=="undefined") module.exports = nanomemoize;

@@ -112,0 +88,0 @@ if(typeof(window)!=="undefined") window.nanomemoize = nanomemoize;

@@ -1,1 +0,1 @@

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){(function(){"use strict";const hsVrgs=f=>{const s=f+"",i=s.indexOf("...");return i>=0&&i<s.indexOf(")"||s.indexOf("arguments")>=0)};function nanomemoize(fn,options={}){function sngl(f,s,chng,serializer,arg){const key=!arg||typeof arg==="number"||typeof arg==="boolean"?arg:serializer(arg);if(chng)chng(key);return s[key]||(s[key]=f.call(this,arg))}function mltpl(f,k,v,eq,chng,max=0,...args){const rslt={};for(let i=0;i<k.length;i++){let key=k[i];if(max){key=key.slice(0,max)}if(key.length===args.length||max&&key.length<args.length){const max=key.length-1;for(let j=0;j<=max;j++){if(!eq(key[j],args[j])){break}if(j===max){rslt.i=i;rslt.v=v[i]}}}}const i=rslt.i>=0?rslt.i:v.length;if(chng){chng(i)}return typeof rslt.v==="undefined"?v[i]=f.call(this,...k[i]=args):rslt.v}const{serializer:serializer=(value=>JSON.stringify(value)),equals:equals,maxAge:maxAge,maxArgs:maxArgs,vargs:vargs=hsVrgs(fn),expireInterval:expireInterval=1}=options,s={},k=[],v=[],c={},chng=(cache,key)=>{c[key]={key:key,cache:cache}},t={},tmout=chng=>{if(t[chng.key]){clearTimeout(t[chng.key])}t[chng.key]=setTimeout(()=>{delete chng.cache[chng.key];delete t[chng.key]},maxAge)};let f,unry=fn.length===1&&!equals&&!vargs;if(unry){f=sngl.bind(this,fn,s,maxAge?chng.bind(this,s):null,serializer)}else{f=mltpl.bind(this,fn,k,v,equals||((a,b)=>a===b),maxAge?chng.bind(this,v):null,maxArgs)}f.clear=(()=>{Object.keys(s).forEach(k=>delete s[k]);k.length=0;v.length=0;Object.keys(c).forEach(k=>delete c[k]);Object.keys(t).forEach(k=>{clearTimeout(t[k]);delete t[k]})});f.keys=(()=>!unry?k.slice():null);f.values=(()=>!unry?v.slice():null);f.keyValues=(()=>unry?Object.assign({},s):null);if(expireInterval){f.interval=setInterval(()=>{for(const p in c){if(maxAge){tmout(c[p])}delete c[p]}},expireInterval)}return f}if(typeof module!=="undefined")module.exports=nanomemoize;if(typeof window!=="undefined")window.nanomemoize=nanomemoize}).call(this)},{}]},{},[1]);
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){(function(){"use strict";const hsVrgs=f=>{const s=f+"",i=s.indexOf("...");return i>=0&&i<s.indexOf(")"||s.indexOf("arguments")>=0)};function nanomemoize(fn,options={}){const{serializer:serializer=(value=>JSON.stringify(value)),equals:equals,maxAge:maxAge,maxArgs:maxArgs,vargs:vargs=hsVrgs(fn)}=options,s={},k=[],v=[];function sngl(f,s,chng,serializer,arg){const key=!arg||typeof arg==="number"||typeof arg==="boolean"?arg:serializer(arg);if(chng)chng(key);return s[key]||(s[key]=f.call(this,arg))}function mltpl(f,k,v,eq,chng,max=0,...args){const rslt={};for(let i=0;i<k.length;i++){let key=k[i];if(max){key=key.slice(0,max)}if(key.length===args.length||max&&key.length<args.length){const max=key.length-1;for(let j=0;j<=max;j++){if(!eq(key[j],args[j])){break}if(j===max){rslt.i=i;rslt.v=v[i]}}}}const i=rslt.i>=0?rslt.i:v.length;if(chng)chng(i);return typeof rslt.v==="undefined"?v[i]=f.call(this,...k[i]=args):rslt.v}let m,unry=fn.length===1&&!equals&&!vargs;if(unry){m=sngl.bind(this,fn,s,maxAge?key=>setTimeout(()=>{delete s[key]},maxAge):null,serializer)}else{m=mltpl.bind(this,fn,k,v,equals||((a,b)=>a===b),maxAge?key=>setTimeout(()=>{delete v[key]},maxAge):null,maxArgs)}m.clear=(()=>{Object.keys(s).forEach(k=>delete s[k]);k.length=0;v.length=0});m.keys=(()=>!unry?k.slice():null);m.values=(()=>!unry?v.slice():null);m.keyValues=(()=>unry?Object.assign({},s):null);return m}if(typeof module!=="undefined")module.exports=nanomemoize;if(typeof window!=="undefined")window.nanomemoize=nanomemoize}).call(this)},{}]},{},[1]);

@@ -9,3 +9,13 @@ (function() {

function nanomemoize (fn, options={}) {
// for sngl argument functions, just use a JS object key look-up
const {
serializer = (value) => JSON.stringify(value),
equals,
maxAge,
maxArgs,
vargs = hsVrgs(fn)
} = options,
s = {}, // single arg function key/value cache
k = [], // multiple arg function arg key cache
v = []; // multiple arg function result cache
// for single argument functions, just use a JS object key look-up
function sngl (f,s,chng,serializer,arg) {

@@ -15,5 +25,5 @@ // strings must be stringified because cache[1] should not equal or overwrite cache["1"] for value = 1 and value = "1"

if(chng) chng(key);
return s[key] || ( s[key] = f.call(this, arg));
return s[key] || (s[key] = f.call(this, arg));
}
// for mltpl arg functions, loop through a cache of all the args
// for multiple arg functions, loop through a cache of all the args
// looking at each arg separately so a test can abort as soon as possible

@@ -37,41 +47,18 @@ function mltpl(f,k,v,eq,chng,max=0,...args) {

const i = rslt.i>=0 ? rslt.i : v.length;
if(chng) { chng(i); }
if(chng) chng(i);
return typeof rslt.v === "undefined" ? v[i] = f.call(this,...(k[i] = args)) : rslt.v;
}
const {
serializer = (value) => JSON.stringify(value),
equals,
maxAge,
maxArgs,
vargs = hsVrgs(fn),
expireInterval = 1
} = options,
s = {}, // sngl arg function key/value cache
k = [], // mltpl arg function arg key cache
v = [], // mltpl arg function result cache
c = {}, // key chng cache
chng = (cache,key) => { // logs key chngs
c[key] = {key,cache};
},
t = {},
tmout = (chng) => { // deletes timed-out keys
if(t[chng.key]) { clearTimeout(t[chng.key]); }
t[chng.key] = setTimeout(() => {
delete chng.cache[chng.key];
delete t[chng.key];
},maxAge);
};
let f,
let m,
unry = fn.length===1 && !equals && !vargs;
// pre-bind core arguments, faster than using a closure or passing on stack or in this case using a partial
if(unry) {
f = sngl.bind(
m = sngl.bind(
this,
fn,
s,
(maxAge ? chng.bind(this,s): null), // turn chng logging on and bind to arg cache s
maxAge ? (key) => setTimeout(() => { delete s[key]; },maxAge) : null,
serializer
);
} else {
f = mltpl.bind(
m = mltpl.bind(
this,

@@ -82,3 +69,3 @@ fn,

equals || ((a,b) => a===b), // default to just a regular strict comparison
(maxAge ? chng.bind(this,v): null), // turn chng logging on and bind to arg cache v
maxAge ? (key) => setTimeout(() => { delete v[key]; },maxAge) : null,
maxArgs

@@ -88,23 +75,12 @@ );

// reset all the caches, must chng array length or delete keys on objects to retain bind integrity
f.clear = () => {
m.clear = () => {
Object.keys(s).forEach((k) => delete s[k]);
k.length = 0; //k.splice(0,k.length);
v.length = 0; //v.splice(0,v.length);
Object.keys(c).forEach(k => delete c[k]);
Object.keys(t).forEach(k => { clearTimeout(t[k]); delete t[k]; });
k.length = 0;
v.length = 0;
};
f.keys = () => (!unry ? k.slice() : null);
f.values = () => (!unry ? v.slice() : null);
f.keyValues = () => (unry ? Object.assign({},s) : null);
if(expireInterval) {
f.interval = setInterval(() => { // process key chngs out of cycle for speed
for(const p in c) {
if(maxAge) { tmout(c[p]); }
delete c[p];
}
},expireInterval);
}
return f;
m.keys = () => (!unry ? k.slice() : null);
m.values = () => (!unry ? v.slice() : null);
m.keyValues = () => (unry ? Object.assign({},s) : null);
return m;
}
if(typeof(module)!=="undefined") module.exports = nanomemoize;

@@ -111,0 +87,0 @@ if(typeof(window)!=="undefined") window.nanomemoize = nanomemoize;

@@ -1,1 +0,1 @@

(function(){"use strict";const hsVrgs=f=>{const s=f+"",i=s.indexOf("...");return i>=0&&i<s.indexOf(")"||s.indexOf("arguments")>=0)};function nanomemoize(fn,options={}){function sngl(f,s,chng,serializer,arg){const key=!arg||typeof arg==="number"||typeof arg==="boolean"?arg:serializer(arg);if(chng)chng(key);return s[key]||(s[key]=f.call(this,arg))}function mltpl(f,k,v,eq,chng,max=0,...args){const rslt={};for(let i=0;i<k.length;i++){let key=k[i];if(max){key=key.slice(0,max)}if(key.length===args.length||max&&key.length<args.length){const max=key.length-1;for(let j=0;j<=max;j++){if(!eq(key[j],args[j])){break}if(j===max){rslt.i=i;rslt.v=v[i]}}}}const i=rslt.i>=0?rslt.i:v.length;if(chng){chng(i)}return typeof rslt.v==="undefined"?v[i]=f.call(this,...k[i]=args):rslt.v}const{serializer:serializer=(value=>JSON.stringify(value)),equals:equals,maxAge:maxAge,maxArgs:maxArgs,vargs:vargs=hsVrgs(fn),expireInterval:expireInterval=1}=options,s={},k=[],v=[],c={},chng=(cache,key)=>{c[key]={key:key,cache:cache}},t={},tmout=chng=>{if(t[chng.key]){clearTimeout(t[chng.key])}t[chng.key]=setTimeout(()=>{delete chng.cache[chng.key];delete t[chng.key]},maxAge)};let f,unry=fn.length===1&&!equals&&!vargs;if(unry){f=sngl.bind(this,fn,s,maxAge?chng.bind(this,s):null,serializer)}else{f=mltpl.bind(this,fn,k,v,equals||((a,b)=>a===b),maxAge?chng.bind(this,v):null,maxArgs)}f.clear=(()=>{Object.keys(s).forEach(k=>delete s[k]);k.length=0;v.length=0;Object.keys(c).forEach(k=>delete c[k]);Object.keys(t).forEach(k=>{clearTimeout(t[k]);delete t[k]})});f.keys=(()=>!unry?k.slice():null);f.values=(()=>!unry?v.slice():null);f.keyValues=(()=>unry?Object.assign({},s):null);if(expireInterval){f.interval=setInterval(()=>{for(const p in c){if(maxAge){tmout(c[p])}delete c[p]}},expireInterval)}return f}if(typeof module!=="undefined")module.exports=nanomemoize;if(typeof window!=="undefined")window.nanomemoize=nanomemoize}).call(this);
(function(){"use strict";const hsVrgs=f=>{const s=f+"",i=s.indexOf("...");return i>=0&&i<s.indexOf(")"||s.indexOf("arguments")>=0)};function nanomemoize(fn,options={}){const{serializer:serializer=(value=>JSON.stringify(value)),equals:equals,maxAge:maxAge,maxArgs:maxArgs,vargs:vargs=hsVrgs(fn)}=options,s={},k=[],v=[];function sngl(f,s,chng,serializer,arg){const key=!arg||typeof arg==="number"||typeof arg==="boolean"?arg:serializer(arg);if(chng)chng(key);return s[key]||(s[key]=f.call(this,arg))}function mltpl(f,k,v,eq,chng,max=0,...args){const rslt={};for(let i=0;i<k.length;i++){let key=k[i];if(max){key=key.slice(0,max)}if(key.length===args.length||max&&key.length<args.length){const max=key.length-1;for(let j=0;j<=max;j++){if(!eq(key[j],args[j])){break}if(j===max){rslt.i=i;rslt.v=v[i]}}}}const i=rslt.i>=0?rslt.i:v.length;if(chng)chng(i);return typeof rslt.v==="undefined"?v[i]=f.call(this,...k[i]=args):rslt.v}let m,unry=fn.length===1&&!equals&&!vargs;if(unry){m=sngl.bind(this,fn,s,maxAge?key=>setTimeout(()=>{delete s[key]},maxAge):null,serializer)}else{m=mltpl.bind(this,fn,k,v,equals||((a,b)=>a===b),maxAge?key=>setTimeout(()=>{delete v[key]},maxAge):null,maxArgs)}m.clear=(()=>{Object.keys(s).forEach(k=>delete s[k]);k.length=0;v.length=0});m.keys=(()=>!unry?k.slice():null);m.values=(()=>!unry?v.slice():null);m.keyValues=(()=>unry?Object.assign({},s):null);return m}if(typeof module!=="undefined")module.exports=nanomemoize;if(typeof window!=="undefined")window.nanomemoize=nanomemoize}).call(this);

@@ -9,3 +9,13 @@ (function() {

function nanomemoize (fn, options={}) {
// for sngl argument functions, just use a JS object key look-up
const {
serializer = (value) => JSON.stringify(value),
equals,
maxAge,
maxArgs,
vargs = hsVrgs(fn)
} = options,
s = {}, // single arg function key/value cache
k = [], // multiple arg function arg key cache
v = []; // multiple arg function result cache
// for single argument functions, just use a JS object key look-up
function sngl (f,s,chng,serializer,arg) {

@@ -15,5 +25,5 @@ // strings must be stringified because cache[1] should not equal or overwrite cache["1"] for value = 1 and value = "1"

if(chng) chng(key);
return s[key] || ( s[key] = f.call(this, arg));
return s[key] || (s[key] = f.call(this, arg));
}
// for mltpl arg functions, loop through a cache of all the args
// for multiple arg functions, loop through a cache of all the args
// looking at each arg separately so a test can abort as soon as possible

@@ -37,41 +47,18 @@ function mltpl(f,k,v,eq,chng,max=0,...args) {

const i = rslt.i>=0 ? rslt.i : v.length;
if(chng) { chng(i); }
if(chng) chng(i);
return typeof rslt.v === "undefined" ? v[i] = f.call(this,...(k[i] = args)) : rslt.v;
}
const {
serializer = (value) => JSON.stringify(value),
equals,
maxAge,
maxArgs,
vargs = hsVrgs(fn),
expireInterval = 1
} = options,
s = {}, // sngl arg function key/value cache
k = [], // mltpl arg function arg key cache
v = [], // mltpl arg function result cache
c = {}, // key chng cache
chng = (cache,key) => { // logs key chngs
c[key] = {key,cache};
},
t = {},
tmout = (chng) => { // deletes timed-out keys
if(t[chng.key]) { clearTimeout(t[chng.key]); }
t[chng.key] = setTimeout(() => {
delete chng.cache[chng.key];
delete t[chng.key];
},maxAge);
};
let f,
let m,
unry = fn.length===1 && !equals && !vargs;
// pre-bind core arguments, faster than using a closure or passing on stack or in this case using a partial
if(unry) {
f = sngl.bind(
m = sngl.bind(
this,
fn,
s,
(maxAge ? chng.bind(this,s): null), // turn chng logging on and bind to arg cache s
maxAge ? (key) => setTimeout(() => { delete s[key]; },maxAge) : null,
serializer
);
} else {
f = mltpl.bind(
m = mltpl.bind(
this,

@@ -82,3 +69,3 @@ fn,

equals || ((a,b) => a===b), // default to just a regular strict comparison
(maxAge ? chng.bind(this,v): null), // turn chng logging on and bind to arg cache v
maxAge ? (key) => setTimeout(() => { delete v[key]; },maxAge) : null,
maxArgs

@@ -88,23 +75,12 @@ );

// reset all the caches, must chng array length or delete keys on objects to retain bind integrity
f.clear = () => {
m.clear = () => {
Object.keys(s).forEach((k) => delete s[k]);
k.length = 0; //k.splice(0,k.length);
v.length = 0; //v.splice(0,v.length);
Object.keys(c).forEach(k => delete c[k]);
Object.keys(t).forEach(k => { clearTimeout(t[k]); delete t[k]; });
k.length = 0;
v.length = 0;
};
f.keys = () => (!unry ? k.slice() : null);
f.values = () => (!unry ? v.slice() : null);
f.keyValues = () => (unry ? Object.assign({},s) : null);
if(expireInterval) {
f.interval = setInterval(() => { // process key chngs out of cycle for speed
for(const p in c) {
if(maxAge) { tmout(c[p]); }
delete c[p];
}
},expireInterval);
}
return f;
m.keys = () => (!unry ? k.slice() : null);
m.values = () => (!unry ? v.slice() : null);
m.keyValues = () => (unry ? Object.assign({},s) : null);
return m;
}
if(typeof(module)!=="undefined") module.exports = nanomemoize;

@@ -111,0 +87,0 @@ if(typeof(window)!=="undefined") window.nanomemoize = nanomemoize;

{
"name": "nano-memoize",
"version": "v1.0.1",
"version": "v1.0.2",
"description": "Faster than fast, smaller than micro ... a nano speed and nano size memoizer.",

@@ -5,0 +5,0 @@ "engines": {},

@@ -8,3 +8,3 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/30ce201484754fa5b0a6c6046abb842d)](https://www.codacy.com/app/syblackwell/nano-memoize?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=anywhichway/nano-memoize&amp;utm_campaign=Badge_Grade)

The minified/gzipped size is 887 bytes for `nano-memoize` vs 959 bytes for `micro-memoize`. And, `nano-memoize` has slightly more functionality.
The minified/gzipped size is 589 bytes for `nano-memoize` vs 959 bytes for `micro-memoize`. And, `nano-memoize` has slightly more functionality.

@@ -29,3 +29,3 @@ The speed tests are below. In most cases `nano-memoize` is the fastest.

+---------------+-------------+--------------------------+-------------�
� namo-memoize � 277,174,954 � � 0.39% � 94 �
� nano-memoize � 277,174,954 � � 0.39% � 94 �
+---------------+-------------+--------------------------+-------------�

@@ -61,3 +61,3 @@ � fast-memoize � 243,829,313 � � 4.97% � 81 �

+---------------+-------------+--------------------------+-------------�
� namo-memoize � 271,647,146 � 0.74% � 90 �
� nano-memoize � 271,647,146 � 0.74% � 90 �
+---------------+-------------+--------------------------+-------------�

@@ -188,4 +188,2 @@ � micro-memoize � 44,126,430 � 4.22% � 81 �

vargs: boolean
// number of milliseconds between checks to expire memos, defaults to 1, set to 0 if you want to disable
expireInterval: number,
}

@@ -196,2 +194,4 @@ ```

2019-02-16 v1.0.2 Further optimizations to deal with Issue 4. `expireInterval` introduced in v1.0.1 removed since it is no longer needed. Also, 25% reduction in size. Code no longer thrashes when memoizing a large number of functions.
2019-02-16 v1.0.1 Memo expiration optimization. Issue 4 addressed.

@@ -198,0 +198,0 @@

@@ -9,3 +9,13 @@ (function() {

function nanomemoize (fn, options={}) {
// for sngl argument functions, just use a JS object key look-up
const {
serializer = (value) => JSON.stringify(value),
equals,
maxAge,
maxArgs,
vargs = hsVrgs(fn)
} = options,
s = {}, // single arg function key/value cache
k = [], // multiple arg function arg key cache
v = []; // multiple arg function result cache
// for single argument functions, just use a JS object key look-up
function sngl (f,s,chng,serializer,arg) {

@@ -15,5 +25,5 @@ // strings must be stringified because cache[1] should not equal or overwrite cache["1"] for value = 1 and value = "1"

if(chng) chng(key);
return s[key] || ( s[key] = f.call(this, arg));
return s[key] || (s[key] = f.call(this, arg));
}
// for mltpl arg functions, loop through a cache of all the args
// for multiple arg functions, loop through a cache of all the args
// looking at each arg separately so a test can abort as soon as possible

@@ -37,41 +47,18 @@ function mltpl(f,k,v,eq,chng,max=0,...args) {

const i = rslt.i>=0 ? rslt.i : v.length;
if(chng) { chng(i); }
if(chng) chng(i);
return typeof rslt.v === "undefined" ? v[i] = f.call(this,...(k[i] = args)) : rslt.v;
}
const {
serializer = (value) => JSON.stringify(value),
equals,
maxAge,
maxArgs,
vargs = hsVrgs(fn),
expireInterval = 1
} = options,
s = {}, // sngl arg function key/value cache
k = [], // mltpl arg function arg key cache
v = [], // mltpl arg function result cache
c = {}, // key chng cache
chng = (cache,key) => { // logs key chngs
c[key] = {key,cache};
},
t = {},
tmout = (chng) => { // deletes timed-out keys
if(t[chng.key]) { clearTimeout(t[chng.key]); }
t[chng.key] = setTimeout(() => {
delete chng.cache[chng.key];
delete t[chng.key];
},maxAge);
};
let f,
let m,
unry = fn.length===1 && !equals && !vargs;
// pre-bind core arguments, faster than using a closure or passing on stack or in this case using a partial
if(unry) {
f = sngl.bind(
m = sngl.bind(
this,
fn,
s,
(maxAge ? chng.bind(this,s): null), // turn chng logging on and bind to arg cache s
maxAge ? (key) => setTimeout(() => { delete s[key]; },maxAge) : null,
serializer
);
} else {
f = mltpl.bind(
m = mltpl.bind(
this,

@@ -82,3 +69,3 @@ fn,

equals || ((a,b) => a===b), // default to just a regular strict comparison
(maxAge ? chng.bind(this,v): null), // turn chng logging on and bind to arg cache v
maxAge ? (key) => setTimeout(() => { delete v[key]; },maxAge) : null,
maxArgs

@@ -88,23 +75,12 @@ );

// reset all the caches, must chng array length or delete keys on objects to retain bind integrity
f.clear = () => {
m.clear = () => {
Object.keys(s).forEach((k) => delete s[k]);
k.length = 0; //k.splice(0,k.length);
v.length = 0; //v.splice(0,v.length);
Object.keys(c).forEach(k => delete c[k]);
Object.keys(t).forEach(k => { clearTimeout(t[k]); delete t[k]; });
k.length = 0;
v.length = 0;
};
f.keys = () => (!unry ? k.slice() : null);
f.values = () => (!unry ? v.slice() : null);
f.keyValues = () => (unry ? Object.assign({},s) : null);
if(expireInterval) {
f.interval = setInterval(() => { // process key chngs out of cycle for speed
for(const p in c) {
if(maxAge) { tmout(c[p]); }
delete c[p];
}
},expireInterval);
}
return f;
m.keys = () => (!unry ? k.slice() : null);
m.values = () => (!unry ? v.slice() : null);
m.keyValues = () => (unry ? Object.assign({},s) : null);
return m;
}
if(typeof(module)!=="undefined") module.exports = nanomemoize;

@@ -111,0 +87,0 @@ if(typeof(window)!=="undefined") window.nanomemoize = nanomemoize;

@@ -61,3 +61,3 @@ var chai,

});
it("expires content",function(done) {
it("expires content single",function(done) {
const expiring = nanomemoize((a) => a,{maxAge:5});

@@ -71,2 +71,14 @@ expect(expiring(1)).to.equal(1);

});
it("expires content multiple",function(done) {
const expiring = nanomemoize((a,b) => { return {a,b}; },{maxAge:5}),
result = expiring(1,2);
expect(result.a).to.equal(1);
expect(result.b).to.equal(2);
expect(expiring.values()[0].a).to.equal(1);
expect(expiring.values()[0].b).to.equal(2);
setTimeout(() => {
expect(expiring.values()[0]).to.equal(undefined);
done();
},20)
});
it("clear cache",function() {

@@ -73,0 +85,0 @@ const value = 1;

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