Skip to content

Instantly share code, notes, and snippets.

@baruchiro
Created January 15, 2023 15:07
Show Gist options
  • Save baruchiro/23626f91f3772a93bd8d1380864bb66c to your computer and use it in GitHub Desktop.
Save baruchiro/23626f91f3772a93bd8d1380864bb66c to your computer and use it in GitHub Desktop.
Very simple cache function
const _cache = {}
/** @param {string[]} keys */
const buildNewKeys = (keys) => keys.reduce((acc, currentKey) => {
if (!acc[currentKey]) {
acc[currentKey] = {}
}
return acc[currentKey]
}, _cache)
/**
* @template T
* @param {string[] | string} keys
* @param {() => Promise<T>} action
* @returns {Promise<T>}
*/
export default (keys, action) => {
const lastKey = typeof keys === 'string' ? keys : keys.pop()
const objectForKey = typeof keys === 'string' ? _cache : buildNewKeys(keys)
if (!objectForKey[lastKey]) objectForKey[lastKey] = action()
return objectForKey[lastKey]
}
/**
* @jest-environment node
*/
import { describe, expect, it, jest } from '@jest/globals'
import cache from './cache'
const createPromise = (value) => new Promise((resolve) => setImmediate(() => resolve(value)))
describe('cache', () => {
it('should support one key without array', () => {
const expected = 15
const actual = cache('key', () => expected)
expect(actual).toBe(expected)
})
it('should support one key in array', () => {
const expected = 51
const actual = cache(['keys'], () => expected)
expect(actual).toBe(expected)
})
it('should save the value for one key', async () => {
const expected = 1
const another = 2
cache(['expected-key'], () => createPromise(expected))
cache(['another-key'], () => createPromise(another))
const actual = await cache(['expected-key'])
expect(actual).toBe(expected)
})
it('should run cached function only once', async () => {
const fn = jest.fn().mockReturnValue(22)
await Promise.all([
cache('my-key', fn),
cache('my-key', fn),
cache('my-key', fn),
])
expect(fn).toBeCalledTimes(1)
})
it('should save the value for multiple keys', async () => {
const expected = 33
cache(['a', 'b', 'c'], () => expected)
cache(['hi'], () => 2)
cache(['a', 'b', 'd'], () => 2)
const actual = cache(['a', 'b', 'c'])
expect(actual).toBe(expected)
})
it('should return object containing cached results', async () => {
cache(['e', 'f', 'g'], () => 2)
cache(['hi'], () => 2)
cache(['e', 'f', 'h'], () => 2)
expect(cache(['e', 'f'])).toStrictEqual({
g: 2,
h: 2,
})
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment