p-memoize

  • Version 9.0.0
  • Published
  • 35.1 kB
  • 1 dependency
  • MIT license

Install

npm i p-memoize
yarn add p-memoize
pnpm add p-memoize

Overview

Memoize promise-returning & async functions

Index

Functions

function pMemoize

pMemoize: <
FunctionToMemoize extends AnyAsyncFunction,
CacheKeyType = Parameters<FunctionToMemoize>[0]
>(
fn: FunctionToMemoize,
options?: Options<FunctionToMemoize, CacheKeyType>
) => FunctionToMemoize;
  • [Memoize](https://en.wikipedia.org/wiki/Memoization) functions - An optimization used to speed up consecutive function calls by caching the result of calls with identical input.

    For an overloaded function, the option types come from one of its overloads, because ReturnType resolves a type with several call signatures to a single one. Pass both type arguments to pMemoize when that matters.

    Parameter fn

    Function to be memoized.

    Parameter options

    See the Options type above.

    Example 1

    import pMemoize from 'p-memoize';
    import got from 'got';
    const memoizedGot = pMemoize(got);
    await memoizedGot('https://sindresorhus.com');
    // This call is cached
    await memoizedGot('https://sindresorhus.com');

    The default cache keeps every value for as long as the memoized function exists. To let entries expire, pass a cache that does it, which the readme's "Time-based cache expiration" section covers.

function pMemoizeClear

pMemoizeClear: (fn: AnyAsyncFunction) => void;
  • Clear all cached data of a memoized function.

    What the clear reaches depends on what it is clearing:

    - The cache is emptied for every memoized function sharing it, and a call still running on any of them will not write its result back into it. - Only the in-flight calls of fn itself are dropped, so a later call on it starts fresh rather than joining one that began before the clear. Another memoized function over the same cache keeps sharing its own in-flight calls until they settle.

    A cache.set() that has already started when you clear is not undone, so that value can still land in the cleared cache.

    This function is synchronous: a clear() that returns a promise finishes after it returns, and a rejection from it is dropped rather than reported, since there is nothing to return it through. A clear() that throws synchronously still propagates to the caller.

    Parameter fn

    Memoized function.

function pMemoizeDecorator

pMemoizeDecorator: <
FunctionToMemoize extends AnyAsyncFunction = (
...arguments_: any[]
) => Promise<any>,
CacheKeyType = Parameters<FunctionToMemoize>[0]
>(
options?: Options<NoInfer<FunctionToMemoize>, NoInfer<CacheKeyType>>
) => <This, Value extends FunctionToMemoize>(value: Value, context: any) => void;
  • - Only class methods are supported; regular functions are not part of the decorators proposals. - Uses the new ECMAScript decorators (TypeScript 5.0+). Legacy experimentalDecorators are not supported. - Babel’s legacy decorators are not supported as they implement a different proposal variant. - Private methods are not supported. - Put @pMemoizeDecorator() first (topmost) when you combine it with other method decorators. Decorators are applied from the bottom up, so a decorator listed above it replaces the method after it, and the memoized copy is then skipped so that it does not hide that replacement. This happens silently. - A subclass that overrides the method is not memoized for it, and a super.method() call from the override reaches the original, unmemoized method.

    Returns

    A decorator to memoize class methods or static class methods.

    Example 1

    import {pMemoizeDecorator} from 'p-memoize';
    class Example {
    index = 0
    @pMemoizeDecorator()
    async counter() {
    return ++this.index;
    }
    }
    class ExampleWithOptions {
    index = 0
    // Only cache positive results.
    @pMemoizeDecorator({shouldCache: value => value > 0})
    async counter() {
    return ++this.index;
    }
    }

Type Aliases

type AnyAsyncFunction

type AnyAsyncFunction = (...arguments_: readonly any[]) => Promise<unknown | void>;

    type CacheStorage

    type CacheStorage<KeyType, ValueType> = {
    has: (key: KeyType) => Promise<boolean> | boolean;
    get: (key: KeyType) => Promise<ValueType | undefined> | ValueType | undefined;
    set: (key: KeyType, value: ValueType) => Promise<unknown> | unknown;
    /**
    Not used by p-memoize. It is allowed so that a cache which has one can still be passed as an object literal.
    */
    delete?: (key: KeyType) => unknown;
    clear?: () => unknown;
    };

      type Options

      type Options<FunctionToMemoize extends AnyAsyncFunction, CacheKeyType> = {
      /**
      Determines the cache key for storing the result based on the function arguments. By default, __only the first argument is considered__ and it is compared by strict equality, so two objects only share an entry when they are the same one.
      A `cacheKey` function can return any type supported by `Map` (or whatever structure you use in the `cache` option).
      You can have it cache **all** the arguments by value with `JSON.stringify`, if they are compatible:
      ```
      import pMemoize from 'p-memoize';
      pMemoize(function_, {cacheKey: JSON.stringify});
      ```
      Or you can use a more full-featured serializer like [serialize-javascript](https://github.com/yahoo/serialize-javascript) to add support for `RegExp`, `Date` and so on.
      ```
      import pMemoize from 'p-memoize';
      import serializeJavascript from 'serialize-javascript';
      pMemoize(function_, {cacheKey: serializeJavascript});
      ```
      - A call with no arguments has an undefined first argument, so it shares an entry with a call passing `undefined` explicitly. Pass a `cacheKey` that also looks at the argument count to tell them apart.
      - A `cacheKey` that returns a promise is rejected by the type: a promise is a fresh object on every call, so every key would be unique and nothing would ever be memoized.
      - The receiver (`this`) is not part of the key, and `cacheKey` cannot see it. A method memoized on a prototype, or one given a `cache` that is shared between instances, returns whichever instance's result was cached first. Use `pMemoizeDecorator()` without a custom `cache` for methods that depend on the instance.
      @default arguments_ => arguments_[0]
      @example arguments_ => JSON.stringify(arguments_)
      */
      readonly cacheKey?: (
      arguments_: Parameters<FunctionToMemoize>
      ) => CacheKeyType extends PromiseLike<unknown> ? never : CacheKeyType;
      /**
      Use a different cache storage. Must implement the following methods: `.has(key)`, `.get(key)`, and `.set(key, value)`, and optionally `.clear()`. You could for example use a `WeakMap` instead or [`quick-lru`](https://github.com/sindresorhus/quick-lru) for a LRU cache. To disable caching so that only concurrent executions resolve with the same value, pass `false`.
      - `.has()` decides whether there is a hit, and `.get()` is only called on a hit, to supply the value. If the two disagree, for example because the entry is evicted in between, the call resolves to `undefined` without running the function.
      - Its key type must be the one `cacheKey` produces, which by default is the first argument's type. TypeScript cannot always check this, so a cache keyed by something else may only fail at runtime, depending on the cache.
      - A cache with no `.clear()` cannot be emptied by `pMemoizeClear()`, and a `WeakMap` has none.
      @default new Map()
      @example new WeakMap()
      */
      readonly cache?:
      | CacheStorage<CacheKeyType, AsyncReturnType<FunctionToMemoize>>
      | false;
      /**
      Controls whether a fulfilled value should be written to the cache.
      It runs after the function fulfills and before `cache.set`.
      - Omit to keep current behavior (always write).
      - Return `false` to skip writing to the cache (in-flight de-duplication is still cleared).
      - Throw or reject to propagate the error and skip caching. The predicate does not run at all when caching is disabled with `cache: false`.
      @example
      ```
      import pMemoize from 'p-memoize';
      // Only cache defined values
      const getMaybe = pMemoize(async key => db.get(key), {
      shouldCache: value => value !== undefined,
      });
      // Only cache non-empty arrays
      const search = pMemoize(async query => fetchResults(query), {
      shouldCache: value => Array.isArray(value) && value.length > 0,
      });
      ```
      Note: This only affects writes; reads from the cache are unchanged.
      */
      readonly shouldCache?: ShouldCache<
      CacheKeyType,
      AsyncReturnType<FunctionToMemoize>,
      Parameters<FunctionToMemoize>
      >;
      };

        type ShouldCache

        type ShouldCache<
        KeyType,
        ValueType,
        ArgumentsList extends readonly unknown[] = readonly unknown[]
        > = (
        value: ValueType,
        context: {
        key: KeyType;
        argumentsList: ArgumentsList;
        }
        ) => boolean | Promise<boolean>;
        • Controls whether a fulfilled value should be written to the cache.

        Package Files (1)

        Dependencies (1)

        Dev Dependencies (10)

        Peer Dependencies (0)

        No peer dependencies.

        Badge

        To add a badge like this onejsDocs.io badgeto your package's README, use the codes available below.

        You may also use Shields.io to create a custom badge linking to https://www.jsdocs.io/package/p-memoize.

        • Markdown
          [![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue)](https://www.jsdocs.io/package/p-memoize)
        • HTML
          <a href="https://www.jsdocs.io/package/p-memoize"><img src="https://img.shields.io/badge/jsDocs.io-reference-blue" alt="jsDocs.io"></a>