diff --git a/index.d.ts b/index.d.ts index 8bef7ce..800da98 100644 --- a/index.d.ts +++ b/index.d.ts @@ -4,6 +4,13 @@ declare namespace QuickLRU { The maximum number of items before evicting the least recently used items. */ readonly maxSize: number; + + /** + Called right before an item is evicted from the cache. + + Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`). + */ + onEviction?: (key: KeyType, value: ValueType) => void; } } diff --git a/index.js b/index.js index 09ca5c2..7d7032e 100644 --- a/index.js +++ b/index.js @@ -7,6 +7,7 @@ class QuickLRU { } this.maxSize = options.maxSize; + this.onEviction = options.onEviction; this.cache = new Map(); this.oldCache = new Map(); this._size = 0; @@ -18,6 +19,13 @@ class QuickLRU { if (this._size >= this.maxSize) { this._size = 0; + + if (typeof this.onEviction === 'function') { + for (const [key, value] of this.oldCache.entries()) { + this.onEviction(key, value); + } + } + this.oldCache = this.cache; this.cache = new Map(); } diff --git a/readme.md b/readme.md index f7b841e..234294a 100644 --- a/readme.md +++ b/readme.md @@ -45,6 +45,15 @@ Type: `number` The maximum number of items before evicting the least recently used items. +#### onEviction + +*Optional*\ +Type: `(key, value) => void` + +Called right before an item is evicted from the cache. + +Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`). + ### Instance The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop. diff --git a/test.js b/test.js index a3d62e5..dd0a1cd 100644 --- a/test.js +++ b/test.js @@ -182,3 +182,24 @@ test('checks total cache size does not exceed `maxSize`', t => { lru.get('1'); t.is(lru.oldCache.has('1'), false); }); + +test('`onEviction` option method is called after `maxSize` is exceeded', t => { + const expectKey = '1'; + const expectValue = 1; + let isCalled = false; + let actualKey; + let actualValue; + + const onEviction = (key, value) => { + actualKey = key; + actualValue = value; + isCalled = true; + }; + + const lru = new QuickLRU({maxSize: 1, onEviction}); + lru.set(expectKey, expectValue); + lru.set('2', 2); + t.is(actualKey, expectKey); + t.is(actualValue, expectValue); + t.true(isCalled); +});