Skip to content

Commit

Permalink
feat(memoize): 重写实现,支持操作缓存
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Apr 23, 2019
1 parent 088d1f7 commit fa6fbac
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 23 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
"typescript": "^3.3.3333"
},
"dependencies": {
"fast-memoize": "^2.5.1",
"is-chinese-phone-number": "^0.1.9"
}
}
77 changes: 63 additions & 14 deletions src/memoize.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,83 @@
import fastMemoize, { Options } from 'fast-memoize'
import { AnyFunction } from './isFunction'

export interface MemoizeOptions<T extends AnyFunction = AnyFunction> {
/**
* 创建缓存容器。
*/
createCache?(): {
/** 设置缓存 */
set(key: string, value: any): void,
get(key: string): any,
/** 是否存在缓存 */
has(key: string): boolean,
/** 获取缓存 */
get(key: string): any,
/** 删除缓存 */
delete(key: string): void,
/** 清空缓存 */
clear(): void,
},
/**
* 序列化函数实参。
*/
serializer?(...args: Parameters<T>): string,
}

export type MemoizeReturn<T extends AnyFunction = AnyFunction> = T & {
/** 上一次执行函数时的缓存键名 */
lastCacheKey: string,
/** 缓存容器 */
cache: ReturnType<MemoizeOptions['createCache']>,
}

/**
* 函数参数结果缓存。
*
* @param fn 要缓存的函数
* @param [options] 选项
* @returns 缓存化后的函数
*/
export function memoize<T extends AnyFunction>(fn: T, options?: MemoizeOptions<T>): T {
let fastMemoizeOptions: Options<T> = undefined
if (options) {
fastMemoizeOptions = {}
if (options.createCache) {
fastMemoizeOptions.cache = {
create: options.createCache,
} as any
}
if (options.serializer) {
fastMemoizeOptions.serializer = args => options.serializer.apply(null, args as any)
export function memoize<T extends AnyFunction>(
fn: T,
{
createCache = () => {
if (typeof Map === 'function' && Map.prototype.hasOwnProperty('clear')) {
return new Map()
}
const cache = Object.create(null)
return {
set(k, v) {
cache[k] = v
},
has(k) {
return (k in cache)
},
get(k) {
return cache[k]
},
delete(k) {
delete cache[k]
},
clear() {
Object.keys(cache).forEach(k => {
delete cache[k]
})
},
}
},
serializer = (...args) => {
return args.join(')`(')
},
}: MemoizeOptions<T> = {},
): MemoizeReturn<T> {
const cache = createCache()
const memoizedFn: any = (...args: Parameters<T>) => {
const cacheKey = serializer(...args)
memoizedFn.lastCacheKey = cacheKey
if (!cache.has(cacheKey)) {
cache.set(cacheKey, fn(...args))
}
return cache.get(cacheKey)
}
return fastMemoize(fn, fastMemoizeOptions)
memoizedFn.cache = cache
return memoizedFn
}
35 changes: 31 additions & 4 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1739,13 +1739,40 @@ describe('formatTemplate', () => {
})

describe('memoize', () => {
test('ok', () => {
const fn = jest.fn(() => 'ok')
const memoizedFn = vtils.memoize(fn)
const fn = jest.fn(() => 'ok')
const memoizedFn = vtils.memoize(fn)

test('调用原函数成功', () => {
expect(memoizedFn()).toBe('ok')
expect(fn).toBeCalledTimes(1)
})

test('以同样的参数调用原函数将直接返回缓存的值', () => {
expect(memoizedFn()).toBe('ok')
expect(fn).toBeCalledTimes(1)
expect(memoizedFn('hello')).toBe('ok')
})

test('可以修改缓存', () => {
memoizedFn.cache.set(memoizedFn.lastCacheKey, 'hello')
expect(memoizedFn()).toBe('hello')
expect(fn).toBeCalledTimes(1)
})

test('可以获取缓存', () => {
expect(memoizedFn.cache.get(memoizedFn.lastCacheKey)).toBe('hello')
})

test('可以删除缓存', () => {
memoizedFn.cache.delete(memoizedFn.lastCacheKey)
expect(memoizedFn()).toBe('ok')
expect(fn).toBeCalledTimes(2)
})

test('可以清空缓存', () => {
expect(memoizedFn()).toBe('ok')
expect(fn).toBeCalledTimes(2)
memoizedFn.cache.clear()
expect(memoizedFn()).toBe('ok')
expect(fn).toBeCalledTimes(3)
})
})
4 changes: 0 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2540,10 +2540,6 @@ fast-levenshtein@~2.0.4:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"

fast-memoize@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.5.1.tgz#c3519241e80552ce395e1a32dcdde8d1fd680f5d"

fastparse@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
Expand Down

0 comments on commit fa6fbac

Please sign in to comment.