# p-memoize

> Memoize promise-returning & async functions

Latest version **8.0.0** (published 2025-08-14) · MIT license · 0 weekly downloads

## Install

```sh
npm install p-memoize
pnpm add p-memoize
yarn add p-memoize
bun add p-memoize
```

## Health

**Score 50/100 (C)** — status: stable.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

Negative: stale.

## Facts

| | |
|---|---|
| Version | 8.0.0 |
| Published | 2025-08-14 |
| First published | 2016-10-21 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM |
| Node | >=20 |
| Dependencies | 2 |
| Unpacked size | 18 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 451 |
| Author | Sindre Sorhus |
| Maintainers | sindresorhus, fregante |
| Keywords | promise, memoize, mem, memoization, function, cache, caching, optimize, performance, ttl, expire, async, await, promises, time, out, cancel, bluebird |

## Links

- npm: https://www.npmjs.com/package/p-memoize
- Repository: https://github.com/sindresorhus/p-memoize
- Homepage: https://github.com/sindresorhus/p-memoize#readme
- Issues: https://github.com/sindresorhus/p-memoize/issues
- Funding: https://github.com/sindresorhus/p-memoize?sponsor=1
- npm.io page: https://npm.io/package/p-memoize

## Dependencies (2)

- [type-fest](https://npm.io/package/type-fest.md) ^4.41.0
- [mimic-function](https://npm.io/package/mimic-function.md) ^5.0.1

## Alternatives

- [express-promise-router](https://npm.io/package/express-promise-router.md) — 736.1K weekly downloads
- [next-usequerystate](https://npm.io/package/next-usequerystate.md) — 29.8K weekly downloads
- [@bitkyc08/opencodex](https://npm.io/package/@bitkyc08/opencodex.md) — 4.6K weekly downloads
- [lynkr](https://npm.io/package/lynkr.md) — 575 weekly downloads
- [baremetal.js](https://npm.io/package/baremetal.js.md) — 42 weekly downloads

## Recent versions

- 8.0.0 (latest) — 2025-08-14
- 4.0.4 (version4) — 2022-01-03
- 7.1.1 — 2022-10-07
- 7.1.0 — 2022-07-05
- 7.0.0 — 2022-07-03
- 6.0.2 — 2022-06-11
- 4.0.3 — 2021-11-14
- 6.0.1 — 2021-10-16
- 6.0.0 — 2021-10-13
- 5.0.1 — 2021-10-05
- 5.0.0 — 2021-09-19
- 4.0.2 — 2021-09-17
- 4.0.1 — 2020-09-24
- 4.0.0 — 2020-02-17
- 4.0.0-1 — 2019-11-29
- … 6 more at https://npm.io/package/p-memoize/versions

## README

# p-memoize

> [Memoize](https://en.wikipedia.org/wiki/Memoization) promise-returning & async functions

Useful for speeding up consecutive function calls by caching the result of calls with identical input.

<!-- Please keep this section in sync with https://github.com/sindresorhus/memoize/blob/main/readme.md -->

By default, **only the memoized function's first argument is considered** via strict equality comparison. If you need to cache multiple arguments or cache `object`s *by value*, have a look at alternative [caching strategies](#caching-strategy) below.

This package is similar to [memoize](https://github.com/sindresorhus/memoize) but with async-specific enhancements; in particular, it allows for asynchronous caches and does not cache rejected promises.

## Install

```sh
npm install p-memoize
```

## Usage

```js
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');
```

### Caching strategy

Similar to the [caching strategy for `memoize`](https://github.com/sindresorhus/memoize#options) with the following exceptions:

- Promises returned from a memoized function are locally cached until resolving, when their value is added to `cache`. Special properties assigned to a returned promise will not be kept after resolution and every promise may need to resolve with a serializable object if caching results in a database.
- `.get()`, `.has()` and `.set()` methods on `cache` can run asynchronously by returning a promise.
- Instead of `.set()` being provided an object with the properties `value` and `maxAge`, it will only be provided `value` as the first argument. If you want to implement time-based expiry, consider [doing so in `cache`](#time-based-cache-expiration).

## API

### pMemoize(fn, options?)

Returns a memoized version of the given function.

#### fn

Type: `Function`

Promise-returning or async function to be memoized.

#### options

Type: `object`

##### cacheKey

Type: `Function`\
Default: `arguments_ => arguments_[0]`\
Example: `arguments_ => JSON.stringify(arguments_)`

Determines the cache key for storing the result based on the function arguments. By default, **only the first argument is considered**.

A `cacheKey` function can return any type supported by `Map` (or whatever structure you use in the `cache` option).

See the [caching strategy](#caching-strategy) section for more information.

##### cache

Type: `object | false`\
Default: `new Map()`

Use a different cache storage. Must implement the following methods: `.has(key)`, `.get(key)`, `.set(key, value)`, `.delete(key)`, 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`.

See the [caching strategy](https://github.com/sindresorhus/mem#caching-strategy) section in the `mem` package for more information.

##### shouldCache

Type: `(value, {key, argumentsList}) => boolean | Promise<boolean>`

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.

```js
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: Affects only writes; reads from the cache are unchanged.

### pMemoizeDecorator(options)

Returns a decorator to memoize class methods (instance and static).

Notes:

- Only class methods are supported; regular functions are not part of the decorators proposals.
- Requires 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.

#### options

Type: `object`

Same as options for `pMemoize()`.

```ts
import {pMemoizeDecorator} from 'p-memoize';

class Example {
	index = 0

	@pMemoizeDecorator()
	async counter() {
		return ++this.index;
	}
}

class ExampleWithOptions {
	index = 0

	@pMemoizeDecorator()
	async counter() {
		return ++this.index;
	}
}
```

The decorator memoizes per-instance. You can clear the cache for an instance method using `pMemoizeClear(instance.method)`.

### pMemoizeClear(memoized)

Clear all cached data of a memoized function.

It will throw when given a non-memoized function.

## Tips

### Time-based cache expiration

```js
import pMemoize from 'p-memoize';
import ExpiryMap from 'expiry-map';
import got from 'got';

const cache = new ExpiryMap(10000); // Cached values expire after 10 seconds

const memoizedGot = pMemoize(got, {cache});
```

### Caching promise rejections

```js
import pMemoize from 'p-memoize';
import pReflect from 'p-reflect';

const memoizedGot = pMemoize(async (url, options) => pReflect(got(url, options)));

await memoizedGot('https://example.com');
// {isFulfilled: true, isRejected: false, value: '...'}
```

## Related

- [p-debounce](https://github.com/sindresorhus/p-debounce) - Debounce promise-returning & async functions
- [p-throttle](https://github.com/sindresorhus/p-throttle) - Throttle promise-returning & async functions
- [More…](https://github.com/sindresorhus/promise-fun)

---
_Source: https://npm.io/package/p-memoize · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
