Giter Club home page Giter Club logo

nano-memoize's People

Contributors

1j01 avatar anywhichway avatar crapthings avatar dependabot[bot] avatar gnarea avatar igalklebanov avatar markogresak avatar mltucker avatar silverwind avatar sirhall avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nano-memoize's Issues

clearing cache with max age

Hello,

I'm using your lib like this:

const memo = nanomemoize(fn, { maxAge: 7_200_000 })

memo()
...
memo.clear()

While calling memo.clear() clears the cache, the setTimeout is not cleared and the process hangs.

Feature idea: Passing dependencies to the memoizer

It is common to have functions that have an external dependency. Think about how React/Redux works with a PureComponent: if any of the Redux dependencies for a page changes, the page's refresh is called to recalculate the layout.

For very complex functions that have a nested tree of calls, it would be very useful to be able to trigger recalculation when not only the direct arguments passed to the function are called, but also a list of dependencies that would be shallowly equated.

Here is a simple example.

const complexFn = mem((someId) => {
   const a = someExternalData.filter(t => t.id === someId);
  
   return doSomethingWithA()
}, { deps: [someExternalData]});

If this is not something worth putting in, could I get some advice on how to implement it? The codebase here is beautifully succinct but somewhat difficult to decipher!

Question: How to clear the cache?

Hello!

First, this is really useful, thanks for creating it :)

I just have one question: how to clear the cache?

I'm using it like this: const css = memoize(_css_, { serializer: hash }) but I'll need to clear all the cache at some point on the app. How to do this? Changing the hash?

Thanks!

IE 11 supported?

Is nano-memoize supported on IE11?

I am trying to use Nano-memoize in my web application which also uses Typescript and Webpack to transpile the code to ES5. However the webpage simply fails to load in IE 11. It works in Chrome.

I have followed the following steps:

  • npm install nano-memoize
  • added import 'nano-memoize/browser/nano-memoize' to my source file.
  • memoized a function like const memoizedFunc = nanomemoize(myFunc)

(the web application is based on create-react-app but the memoized function is not directly used in React components).

Options hash

A lot of our functions accept options hashes, e.g.

const nanoMemoize = require("nano-memoize");
const fn = ({ foo, bar }) => { ... };
const mfn = nanoMemoize(fn);
const fib = new Fib();
mfn({ foo: 'foo', bar: fib }); // miss
mfn({ foo: 'foo', bar: fib }); // miss :(

I understand nano-memoize provides options.seralizer and options.equals but I'm not quite sure how to use them to get a hit on the second call?

callTimeout option notworking

i set callTimeout for reset caching but dont work

node: 18.12.1
nano-memoize: 2.0.0
docker image: node:18.12.1

const checkAccess = memoization(async function (user, ip) {
const type = typeApproach(user)

switch (type) {
    case 'easy':
        const checkTraffic = await checkMaximumTraffic(user)
        report(checkTraffic.resultCheck, user, ip)
        return checkTraffic
    case 'hard':
        const result = await hardApproach(user, ip)

        report(result.resultCheck, user, ip)
        return result
}

}, { callTimeout: 5000 }) //5 seconds

Missing serializer causes `TypeError: p is not a function`

Version 1.1.1 removes the default serializer arg (serializer = value => JSON.stringify(value)).

This breaks the case where the single argument to the memoized function is itself a function:

> const memoize = require('nano-memoize')
undefined
> const memoized = memoize(fn => o => fn(o))
undefined
> const myFunc = memoized(o => console.log(o))
TypeError: p is not a function
    at Object.<anonymous> (/Users/aaronmccall/Projects/phytochrome-web-ui/node_modules/nano-memoize/index.js:35:118)
>

Benchmarking is flawed and nano-memoize is much slower in realistic scenarios

The benchmarking in this repository only tests for the memoized function to be called with the same arguments millions of times. That is not a realistic scenario and one would just put the return value of the original function into a variable. If you test for a realistic scenario, with say, the function being called with 5000 different values the results for nano-memoize look very different. Here are the numbers for a more realistic scenario I ran with the benchmarking:

Name Ops / sec Relative margin of error Sample size
lodash 4,231 ± 0.45% 97
underscore 3,677 ± 0.29% 99
iMemoized 2,237 ± 0.29% 97
memoizee 2,228 ± 0.39% 97
addy-osmani 1,163 ± 0.87% 97
micro-memoize 784 ± 0.36% 95
moize 734 ± 0.19% 96
fast-memoize 433 ± 0.31% 93
memoizerific 44 ± 8.67% 62
nano-memoize 28 ± 2.23% 51
lru-memoize 15 ± 8.55% 44

Here is the code I used for the more realistic benchmarking. You can just copy / paste it into your repo and run it:

function dateToWeekDay(year, month, day) {
  const d = new Date(Date.UTC(year, month, day));
  return d.getDay();
}

const days = [];
const date = new Date(Date.UTC(2023, 0, 1));
for (let i = 0; i < 5000; i++) {
  date.setDate(date.getDate() + 1);
  days.push([date.getFullYear(), date.getMonth(), date.getDate()]);
}

const runRealisticScenario = () => {
  const suite = new Benchmark.Suite("Realistic scenario");

  const mUnderscore = underscore(dateToWeekDay);
  const mLodash = lodash(dateToWeekDay);
  // const mRamda = ramda(dateToMonth);
  const mMemoizee = memoizee(dateToWeekDay);
  const mFastMemoize = fastMemoize(dateToWeekDay);
  const mAddyOsmani = addyOsmani(dateToWeekDay);
  const mMemoizerific = memoizerific(Infinity)(dateToWeekDay);
  const mLruMemoize = lruMemoize(Infinity)(dateToWeekDay);
  const mMoize = moize(dateToWeekDay);
  const mMicroMemoize = microMemoize(dateToWeekDay);
  const mIMemoized = iMemoized.memoize(dateToWeekDay);
  const mNano = nanomemoize(dateToWeekDay);

  return new Promise((resolve) => {
    suite
      .add("nano-memoize", () => {
        for (let i = 0; i < days.length; i++) {
          mNano(...days[i]);
        }
      })
      .add("addy-osmani", () => {
        for (let i = 0; i < days.length; i++) {
          mAddyOsmani(...days[i]);
        }
      })
      .add("lodash", () => {
        for (let i = 0; i < days.length; i++) {
          mLodash(...days[i]);
        }
      })
      .add("lru-memoize", () => {
        for (let i = 0; i < days.length; i++) {
          mLruMemoize(...days[i]);
        }
      })
      .add("memoizee", () => {
        for (let i = 0; i < days.length; i++) {
          mMemoizee(...days[i]);
        }
      })
      .add("memoizerific", () => {
        for (let i = 0; i < days.length; i++) {
          mMemoizerific(...days[i]);
        }
      })
      /*.add('ramda', () => {
        mRamda(fibonacciNumber);
      })*/
      .add("underscore", () => {
        for (let i = 0; i < days.length; i++) {
          mUnderscore(...days[i]);
        }
      })
      .add("iMemoized", () => {
        for (let i = 0; i < days.length; i++) {
          mIMemoized(...days[i]);
        }
      })
      .add("micro-memoize", () => {
        for (let i = 0; i < days.length; i++) {
          mMicroMemoize(...days[i]);
        }
      })
      .add("moize", () => {
        for (let i = 0; i < days.length; i++) {
          mMoize(...days[i]);
        }
      })
      .add("fast-memoize", () => {
        for (let i = 0; i < days.length; i++) {
          mFastMemoize(...days[i]);
        }
      })
      .on("start", () => {
        console.log(""); // eslint-disable-line no-console
        console.log("Starting cycles for functions with realistic scenario..."); // eslint-disable-line no-console

        results = [];

        spinner.start();
      })
      .on("cycle", onCycle)
      .on("complete", () => {
        onComplete();
        resolve();
      })
      .run({
        async: true,
      });
  });
};

Issue with `equals` since 3.0.0 with `fast-deep-equal`

After upgrading from 2.0.0 to 3.0.1, various unit tests on memoized functions started to fail for me. I'm using fast-deep-equal as the comparison function, e.g.:

import fastDeepEqual from "fast-deep-equal";
import nanomemoize from "nano-memoize";

const memoFn = fn => nanomemoize(fn, {equals: fastDeepEqual});

I see the README mentions this specific issue with other modules but does not mention this module yet, so I thought I mention it.

Cannot build React app using nano-memoize

Cannot build react app using nano-memoize (v1.0.0):

$ yarn build
yarn run v1.7.0
$ node scripts/build.js
Creating an optimized production build...
Failed to compile.

Failed to minify the code from this file: 

 	../my-project/node_modules/nano-memoize/index.js:3 

Read more here: http://bit.ly/2tRViJ9

The reference says:

Some third-party packages don't compile their code to ES5 before publishing to npm. This often causes problems in the ecosystem because neither browsers (except for most modern versions) nor some tools currently support all ES6 features. We recommend to publish code on npm as ES5 at least for a few more years.

TypeScript definitions

Hi,

Trying nano-memoize, I realized there isn't any TypeScript definitions whereas some of the compared modules has.

Below is TypeScript definitions for nano-memoize. You may want to optimize serializer and equals, but currently it seems to work fine.

declare module "nano-memoize" {
  export default function memoized<T extends Function>(
    func: T,
    options?: {
      /**
       * Only use the provided maxArgs for cache look-up, useful for ignoring final callback arguments
       */
      maxArgs?: number;
      /**
       * Number of milliseconds to cache a result, set to `Infinity` to never create timers or expire
       */
      maxAge?: number;
      /**
       * The serializer/key generator to use for single argument functions (optional, not recommended)
       * must be able to serialize objects and functions, by default a WeakMap is used internally without serializing
       */
      serializer?: (...args: any[]) => any;
      /**
       * the equals function to use for multi-argument functions (optional, try to avoid) e.g. deepEquals for objects
       */
      equals?: (...args: any[]) => boolean;
      /**
       * Forces the use of multi-argument paradigm, auto set if function has a spread argument or uses `arguments` in its body.
       */
      vargs?: boolean;
    }
  ): T;
}

what does "equals" do?

Hey,

I believe that this option does nothing.


it("optional equal - fastDeepEquals",function() {
		const optionalEqual = nanomemoize(function(a,b) { return [a,b]; },
		    {
			equals:()=> {
					throw new Error("never called")
				}}),
			[a1,a2] = optionalEqual({a:1}, {a:1}),
			values = optionalEqual.values();
		expect(fastDeepEqual(a1,a2)).to.equal(true);
		expect(values[0].length).to.equal(2);
		expect(fastDeepEqual(values[0][0],a1)).to.equal(true);
		expect(fastDeepEqual(values[0][1],a2)).to.equal(true);
	})

I tried to break the tests by throwing but the test is still green

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.