Skip to content

Commit

Permalink
Merge branch 'async-cache' of https://github.com/Richienb/p-memoize i…
Browse files Browse the repository at this point in the history
…nto async-cache
  • Loading branch information
Richienb committed Sep 25, 2021
2 parents c7fa0e7 + dd51838 commit 7f27a9b
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 16 deletions.
12 changes: 7 additions & 5 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,25 +96,27 @@ export default function pMemoize<
cache = new Map(),
}: Options<FunctionToMemoize, CacheKeyType> = {},
): FunctionToMemoize {
const promiseCache = new Map<CacheKeyType, ReturnType<FunctionToMemoize>>();
// Promise objects can't be serialized so we keep track of them internally and only provide their resolved values to `cache`
// `Promise<AsyncReturnType<FunctionToMemoize>>` is used instead of `ReturnType<FunctionToMemoize>` because promise properties are not kept
const promiseCache = new Map<CacheKeyType, Promise<AsyncReturnType<FunctionToMemoize>>>();

const memoized = async function (this: any, ...arguments_: Parameters<FunctionToMemoize>): Promise<AsyncReturnType<FunctionToMemoize>> {
const key = cacheKey ? cacheKey(arguments_) : arguments_[0] as CacheKeyType;

if (promiseCache.has(key)) {
return promiseCache.get(key)! as ReturnType<FunctionToMemoize>; // eslint-disable-line @typescript-eslint/no-unsafe-return
return promiseCache.get(key)!;
}

if (await cache.has(key)) {
return cache.get(key)! as ReturnType<FunctionToMemoize>; // eslint-disable-line @typescript-eslint/no-unsafe-return
return (await cache.get(key))!; // eslint-disable-line @typescript-eslint/no-unsafe-return
}

const promise = fn.apply(this, arguments_) as ReturnType<FunctionToMemoize>;
const promise = fn.apply(this, arguments_);

promiseCache.set(key, promise);

try {
const result = await promise as AsyncReturnType<FunctionToMemoize>;
const result = await promise; // eslint-disable-line @typescript-eslint/no-unsafe-assignment

cache.set(key, result);

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
"@sindresorhus/tsconfig": "^2.0.0",
"@types/serialize-javascript": "^5.0.1",
"ava": "^3.15.0",
"delay": "^5.0.0",
"del-cli": "^4.0.1",
"delay": "^5.0.0",
"serialize-javascript": "^6.0.0",
"ts-node": "^10.2.1",
"tsd": "^0.17.0",
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ await memoizedGot('https://sindresorhus.com');

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

- Promises returned from a memoized function will be cached internally and take priority over `cache`. The promise cache does not persist outside of the current execution and properties assigned to a returned promise are only guaranteed to still exist if a cached promise is available. All cached promises can be cleared with [`pMemoizeClear()`](#pmemoizeclearfn).
- Promises returned from a memoized function will be cached internally and take priority over `cache`. The promise cache does not persist outside of the current instance and properties assigned to a returned promise will not be kept. All cached promises can be cleared with [`pMemoizeClear()`](#pmemoizeclearfn).
- `.get()` and `.has()` methods on `cache` can return a promise instead of returning a value immediately.
- 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 `.set()` itself.

Expand Down
9 changes: 0 additions & 9 deletions test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,6 @@ test('cache option', async t => {
t.is(await memoized(bar), 1);
});

test('promise support', async t => {
let i = 0;
const memoized = pMemoize(async () => i++);
t.is(await memoized(), 0);
t.is(await memoized(), 0);
// @ts-expect-error Argument type does not match
t.is(await memoized(10), 1);
});

test('preserves the original function name', t => {
t.is(pMemoize(async function foo() {}).name, 'foo'); // eslint-disable-line func-names, @typescript-eslint/no-empty-function
});
Expand Down

0 comments on commit 7f27a9b

Please sign in to comment.