UNPKG

5.01 kBMarkdownView Raw
1# p-memoize
2
3> [Memoize](https://en.wikipedia.org/wiki/Memoization) promise-returning & async functions
4
5Useful for speeding up consecutive function calls by caching the result of calls with identical input.
6
7<!-- Please keep this section in sync with https://github.com/sindresorhus/mem/blob/main/readme.md -->
8
9By 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.
10
11This package is similar to [mem](https://github.com/sindresorhus/mem) but with async-specific enhancements; in particular, it allows for asynchronous caches and does not cache rejected promises.
12
13## Install
14
15```sh
16npm install p-memoize
17```
18
19## Usage
20
21```js
22import pMemoize from 'p-memoize';
23import got from 'got';
24
25const memoizedGot = pMemoize(got);
26
27await memoizedGot('https://sindresorhus.com');
28
29// This call is cached
30await memoizedGot('https://sindresorhus.com');
31```
32
33### Caching strategy
34
35Similar to the [caching strategy for `mem`](https://github.com/sindresorhus/mem#options) with the following exceptions:
36
37- 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.
38- `.get()`, `.has()` and `.set()` methods on `cache` can run asynchronously by returning a promise.
39- 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).
40
41## API
42
43### pMemoize(fn, options?)
44
45Returns a memoized version of the given function.
46
47#### fn
48
49Type: `Function`
50
51Promise-returning or async function to be memoized.
52
53#### options
54
55Type: `object`
56
57##### cacheKey
58
59Type: `Function`\
60Default: `arguments_ => arguments_[0]`\
61Example: `arguments_ => JSON.stringify(arguments_)`
62
63Determines the cache key for storing the result based on the function arguments. By default, **only the first argument is considered**.
64
65A `cacheKey` function can return any type supported by `Map` (or whatever structure you use in the `cache` option).
66
67See the [caching strategy](#caching-strategy) section for more information.
68
69##### cache
70
71Type: `object | false`\
72Default: `new Map()`
73
74Use 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`.
75
76See the [caching strategy](https://github.com/sindresorhus/mem#caching-strategy) section in the `mem` package for more information.
77
78### pMemoizeDecorator(options)
79
80Returns a [decorator](https://github.com/tc39/proposal-decorators) to memoize class methods or static class methods.
81
82Notes:
83
84- Only class methods and getters/setters can be memoized, not regular functions (they aren't part of the proposal);
85- Only [TypeScript’s decorators](https://www.typescriptlang.org/docs/handbook/decorators.html#parameter-decorators) are supported, not [Babel’s](https://babeljs.io/docs/en/babel-plugin-proposal-decorators), which use a different version of the proposal;
86- Being an experimental feature, they need to be enabled with `--experimentalDecorators`; follow TypeScript’s docs.
87
88#### options
89
90Type: `object`
91
92Same as options for `pMemoize()`.
93
94```ts
95import {pMemoizeDecorator} from 'p-memoize';
96
97class Example {
98 index = 0
99
100 @pMemoizeDecorator()
101 async counter() {
102 return ++this.index;
103 }
104}
105
106class ExampleWithOptions {
107 index = 0
108
109 @pMemoizeDecorator()
110 async counter() {
111 return ++this.index;
112 }
113}
114```
115
116### pMemoizeClear(memoized)
117
118Clear all cached data of a memoized function.
119
120It will throw when given a non-memoized function.
121
122## Tips
123
124### Time-based cache expiration
125
126```js
127import pMemoize from 'p-memoize';
128import ExpiryMap from 'expiry-map';
129import got from 'got';
130
131const cache = new ExpiryMap(10000); // Cached values expire after 10 seconds
132
133const memoizedGot = pMemoize(got, {cache});
134```
135
136### Caching promise rejections
137
138```js
139import pMemoize from 'p-memoize';
140import pReflect from 'p-reflect';
141
142const memoizedGot = pMemoize(async (url, options) => pReflect(got(url, options)));
143
144await memoizedGot('https://example.com');
145// {isFulfilled: true, isRejected: false, value: '...'}
146```
147
148## Related
149
150- [p-debounce](https://github.com/sindresorhus/p-debounce) - Debounce promise-returning & async functions
151- [p-throttle](https://github.com/sindresorhus/p-throttle) - Throttle promise-returning & async functions
152- [More…](https://github.com/sindresorhus/promise-fun)