├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── cjs
├── index.js
└── package.json
├── esm
└── index.js
├── index.js
├── new.js
├── package.json
├── rollup
├── index.config.js
└── new.config.js
└── test
├── benchmark-basic-lru.js
├── benchmark-lru-cache.js
├── benchmark-lru-map.js
├── benchmark-lru.js
├── benchmark-quick-lru.js
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .nyc_output/
2 | node_modules/
3 | package-lock.json
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .nyc_output/
2 | node_modules/
3 | rollup/
4 | test/
5 | package-lock.json
6 | .travis.yml
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - stable
4 | git:
5 | depth: 1
6 | branches:
7 | only:
8 | - master
9 | - /^greenkeeper/.*$/
10 | after_success:
11 | - "npm run coveralls"
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | ISC License
2 |
3 | Copyright (c) 2020, Andrea Giammarchi, @WebReflection
4 |
5 | Permission to use, copy, modify, and/or distribute this software for any
6 | purpose with or without fee is hereby granted, provided that the above
7 | copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 | PERFORMANCE OF THIS SOFTWARE.
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # basic-lru
2 |
3 | **Social Media Photo by [Mr Cup / Fabien Barral](https://unsplash.com/@iammrcup) on [Unsplash](https://unsplash.com/)**
4 |
5 | [](https://travis-ci.com/WebReflection/basic-lru) [](https://coveralls.io/github/WebReflection/basic-lru?branch=master)
6 |
7 | A fast and lightweight, as in [684 bytes](https://unpkg.com/basic-lru), Map based LRU implementation.
8 |
9 | ```js
10 | import LRU from 'basic-lru';
11 | const LRU = require('basic-lru');
12 | // https://unpkg.com/basic-lru to have LRU globally
13 |
14 | // new LRU(maxSize)
15 | const lru = new LRU(100);
16 |
17 | // new LRU({max}) or new LRU({maxSize})
18 | const lru = new LRU({max: 1000});
19 |
20 | // new LRU({maxAge}) in milliseconds
21 | const lru = new LRU({maxAge: 1000});
22 |
23 | // variants
24 | const lru = new LRU({max: 100, maxAge: 1000});
25 | const lru = new LRU({maxSize: 100, maxAge: 1000});
26 | ```
27 |
28 | ### About
29 |
30 | This module is a drop-in replacement for any [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) instance, and it's mostly 100% compatible with [lru](https://github.com/chriso/lru), [lru-cache](https://github.com/isaacs/node-lru-cache), [quick-lru](https://github.com/sindresorhus/quick-lru), and [lru-map](https://github.com/bchociej/lru-map) modules.
31 |
32 | Differently from other modules, this one has the least amount of LOC, zero dependencies, and it's based on _ES2015_ class capability to extend the native `Map`.
33 |
34 |
35 | ### The Map Extend Differences
36 |
37 | The only difference from a real Map, beside implementing a classic LRU cache, is the `peek(key)` method, to access an entry without flagging its access time anyhow, and borrowed from other libraries, plus a constructor, also borrowed from other libraries, that accepts either an integer, or an options object with `max`, or `maxSize`, and a `maxAge` property, where all of these are optional too.
38 |
--------------------------------------------------------------------------------
/cjs/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const {now} = Date;
3 | const {defineProperties} = Object;
4 | const {iterator} = Symbol;
5 | const zero = {writable: true, value: 0};
6 |
7 | module.exports = class LRU extends Map {
8 |
9 | // constructor overload, same lru signature
10 | constructor(options) {
11 | const n = typeof options === 'number';
12 | const _max = (n ? options : (options.max || options.maxSize)) || Infinity;
13 | const _age = n ? 0 : (options.maxAge || 0);
14 | defineProperties(super(), {
15 | _dropExpired: {value: this._dropExpired.bind(this)},
16 | _dropCount: {value: this._dropCount.bind(this)},
17 | _max: {value: _max},
18 | _age: {value: _age},
19 | _timer: zero,
20 | _drop: zero,
21 | _count: zero
22 | });
23 | }
24 |
25 | // same Map signature overloads
26 | get(key) {
27 | const entry = super.get(key);
28 | if (entry) {
29 | entry.time = now();
30 | return entry.value;
31 | }
32 | }
33 | set(key, value) {
34 | const {_max, _age} = this;
35 | if (!this._drop && this.size === _max)
36 | this._drop = setTimeout(this._dropCount);
37 | if (_age) {
38 | clearTimeout(this._timer);
39 | this._timer = setTimeout(this._dropExpired, _age);
40 | }
41 | return super.set(key, {
42 | count: this._count++,
43 | time: now(),
44 | value
45 | });
46 | }
47 | forEach(callback, self) {
48 | return super.forEach(
49 | ({value}, key) => callback.call(self, value, key, this)
50 | );
51 | }
52 |
53 | // extra methods
54 | peek(key) {
55 | const entry = super.get(key);
56 | if (entry)
57 | return entry.value;
58 | }
59 |
60 | // iterators based overloads
61 | * entries() {
62 | yield * this[iterator]();
63 | }
64 | * values() {
65 | for (const [_, {value}] of super[iterator]())
66 | yield value;
67 | }
68 | * [iterator]() {
69 | for (const [key, {value}] of super[iterator]())
70 | yield [key, value];
71 | }
72 |
73 | // private methods (to be moved as #methods)
74 | _dropCount() {
75 | this._drop = 0;
76 | [...super[iterator]()]
77 | .sort(([_1, entry1], [_2, entry2]) => {
78 | const prop = entry1.time === entry2.time ? 'count' : 'time';
79 | return entry2[prop] - entry1[prop];
80 | })
81 | .slice(this._max)
82 | .forEach(([key]) => this.delete(key));
83 | }
84 | _dropExpired() {
85 | const expiration = now() - this._age;
86 | super.forEach(({time}, key, self) => {
87 | if (time < expiration)
88 | self.delete(key);
89 | });
90 | }
91 | };
92 |
--------------------------------------------------------------------------------
/cjs/package.json:
--------------------------------------------------------------------------------
1 | {"type":"commonjs"}
--------------------------------------------------------------------------------
/esm/index.js:
--------------------------------------------------------------------------------
1 | const {now} = Date;
2 | const {defineProperties} = Object;
3 | const {iterator} = Symbol;
4 | const zero = {writable: true, value: 0};
5 |
6 | export default class LRU extends Map {
7 |
8 | // constructor overload, same lru signature
9 | constructor(options) {
10 | const n = typeof options === 'number';
11 | const _max = (n ? options : (options.max || options.maxSize)) || Infinity;
12 | const _age = n ? 0 : (options.maxAge || 0);
13 | defineProperties(super(), {
14 | _dropExpired: {value: this._dropExpired.bind(this)},
15 | _dropCount: {value: this._dropCount.bind(this)},
16 | _max: {value: _max},
17 | _age: {value: _age},
18 | _timer: zero,
19 | _drop: zero,
20 | _count: zero
21 | });
22 | }
23 |
24 | // same Map signature overloads
25 | get(key) {
26 | const entry = super.get(key);
27 | if (entry) {
28 | entry.time = now();
29 | return entry.value;
30 | }
31 | }
32 | set(key, value) {
33 | const {_max, _age} = this;
34 | if (!this._drop && this.size === _max)
35 | this._drop = setTimeout(this._dropCount);
36 | if (_age) {
37 | clearTimeout(this._timer);
38 | this._timer = setTimeout(this._dropExpired, _age);
39 | }
40 | return super.set(key, {
41 | count: this._count++,
42 | time: now(),
43 | value
44 | });
45 | }
46 | forEach(callback, self) {
47 | return super.forEach(
48 | ({value}, key) => callback.call(self, value, key, this)
49 | );
50 | }
51 |
52 | // extra methods
53 | peek(key) {
54 | const entry = super.get(key);
55 | if (entry)
56 | return entry.value;
57 | }
58 |
59 | // iterators based overloads
60 | * entries() {
61 | yield * this[iterator]();
62 | }
63 | * values() {
64 | for (const [_, {value}] of super[iterator]())
65 | yield value;
66 | }
67 | * [iterator]() {
68 | for (const [key, {value}] of super[iterator]())
69 | yield [key, value];
70 | }
71 |
72 | // private methods (to be moved as #methods)
73 | _dropCount() {
74 | this._drop = 0;
75 | [...super[iterator]()]
76 | .sort(([_1, entry1], [_2, entry2]) => {
77 | const prop = entry1.time === entry2.time ? 'count' : 'time';
78 | return entry2[prop] - entry1[prop];
79 | })
80 | .slice(this._max)
81 | .forEach(([key]) => this.delete(key));
82 | }
83 | _dropExpired() {
84 | const expiration = now() - this._age;
85 | super.forEach(({time}, key, self) => {
86 | if (time < expiration)
87 | self.delete(key);
88 | });
89 | }
90 | };
91 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var LRU = (function (exports) {
2 | 'use strict';
3 |
4 | const {now} = Date;
5 | const {defineProperties} = Object;
6 | const {iterator} = Symbol;
7 | const zero = {writable: true, value: 0};
8 |
9 | class LRU extends Map {
10 |
11 | // constructor overload, same lru signature
12 | constructor(options) {
13 | const n = typeof options === 'number';
14 | const _max = (n ? options : (options.max || options.maxSize)) || Infinity;
15 | const _age = n ? 0 : (options.maxAge || 0);
16 | defineProperties(super(), {
17 | _dropExpired: {value: this._dropExpired.bind(this)},
18 | _dropCount: {value: this._dropCount.bind(this)},
19 | _max: {value: _max},
20 | _age: {value: _age},
21 | _timer: zero,
22 | _drop: zero,
23 | _count: zero
24 | });
25 | }
26 |
27 | // same Map signature overloads
28 | get(key) {
29 | const entry = super.get(key);
30 | if (entry) {
31 | entry.time = now();
32 | return entry.value;
33 | }
34 | }
35 | set(key, value) {
36 | const {_max, _age} = this;
37 | if (!this._drop && this.size === _max)
38 | this._drop = setTimeout(this._dropCount);
39 | if (_age) {
40 | clearTimeout(this._timer);
41 | this._timer = setTimeout(this._dropExpired, _age);
42 | }
43 | return super.set(key, {
44 | count: this._count++,
45 | time: now(),
46 | value
47 | });
48 | }
49 | forEach(callback, self) {
50 | return super.forEach(
51 | ({value}, key) => callback.call(self, value, key, this)
52 | );
53 | }
54 |
55 | // extra methods
56 | peek(key) {
57 | const entry = super.get(key);
58 | if (entry)
59 | return entry.value;
60 | }
61 |
62 | // iterators based overloads
63 | * entries() {
64 | yield * this[iterator]();
65 | }
66 | * values() {
67 | for (const [_, {value}] of super[iterator]())
68 | yield value;
69 | }
70 | * [iterator]() {
71 | for (const [key, {value}] of super[iterator]())
72 | yield [key, value];
73 | }
74 |
75 | // private methods (to be moved as #methods)
76 | _dropCount() {
77 | this._drop = 0;
78 | [...super[iterator]()]
79 | .sort(([_1, entry1], [_2, entry2]) => {
80 | const prop = entry1.time === entry2.time ? 'count' : 'time';
81 | return entry2[prop] - entry1[prop];
82 | })
83 | .slice(this._max)
84 | .forEach(([key]) => this.delete(key));
85 | }
86 | _dropExpired() {
87 | const expiration = now() - this._age;
88 | super.forEach(({time}, key, self) => {
89 | if (time < expiration)
90 | self.delete(key);
91 | });
92 | }
93 | }
94 |
95 | exports.default = LRU;
96 |
97 | return exports;
98 |
99 | }({}).default);
100 |
--------------------------------------------------------------------------------
/new.js:
--------------------------------------------------------------------------------
1 | var LRU=function(e){"use strict";const{now:t}=Date,{defineProperties:r}=Object,{iterator:s}=Symbol,i={writable:!0,value:0};class o extends Map{constructor(e){const t="number"==typeof e,s=(t?e:e.max||e.maxSize)||1/0,o=t?0:e.maxAge||0;r(super(),{_dropExpired:{value:this._dropExpired.bind(this)},_dropCount:{value:this._dropCount.bind(this)},_max:{value:s},_age:{value:o},_timer:i,_drop:i,_count:i})}get(e){const r=super.get(e);if(r)return r.time=t(),r.value}set(e,r){const{_max:s,_age:i}=this;return this._drop||this.size!==s||(this._drop=setTimeout(this._dropCount)),i&&(clearTimeout(this._timer),this._timer=setTimeout(this._dropExpired,i)),super.set(e,{count:this._count++,time:t(),value:r})}forEach(e,t){return super.forEach(({value:r},s)=>e.call(t,r,s,this))}peek(e){const t=super.get(e);if(t)return t.value}*entries(){yield*this[s]()}*values(){for(const[e,{value:t}]of super[s]())yield t}*[s](){for(const[e,{value:t}]of super[s]())yield[e,t]}_dropCount(){this._drop=0,[...super[s]()].sort(([e,t],[r,s])=>{const i=t.time===s.time?"count":"time";return s[i]-t[i]}).slice(this._max).forEach(([e])=>this.delete(e))}_dropExpired(){const e=t()-this._age;super.forEach(({time:t},r,s)=>{t {
58 | console.log(String(event.target))
59 | if (event.target.error)
60 | console.error(event.target.error)
61 | })
62 | .run();
63 |
--------------------------------------------------------------------------------
/test/benchmark-lru-cache.js:
--------------------------------------------------------------------------------
1 | // https://github.com/isaacs/node-lru-cache/blob/master/benchmark/index.js
2 |
3 | 'use strict'
4 |
5 | console.log('\x1b[7m Benchmarking \x1b[1mlru-cache \x1b[0m');
6 |
7 | var benchmark = require('benchmark')
8 |
9 | // function LRU() { const lru = new Map; lru.peek = lru.get; return lru; }
10 | var LRU = require('lru-cache')
11 |
12 | var suite = new benchmark.Suite()
13 |
14 | function add(name, fn) {
15 | suite.add(name, fn)
16 | }
17 |
18 | // SET
19 | var lru1 = new LRU({
20 | max: 1000
21 | })
22 | var lru1Counter = 0
23 |
24 | add(' set', function() {
25 | lru1.set('key' + (lru1Counter++), 'value')
26 | })
27 |
28 | // GET and PEEK
29 | var lru2 = new LRU({
30 | max: 1000
31 | })
32 | var lru2Counter = 0
33 |
34 | for (var i = 0; i < 1000; i++)
35 | lru2.set('key' + i, 'value')
36 |
37 | add(' get', function() {
38 | lru2.get('key' + (lru2Counter++) % 1000)
39 | })
40 |
41 | add(' peek', function() {
42 | lru2.peek('key' + (lru2Counter++) % 1000)
43 | })
44 |
45 | // SET with maxAge
46 | var lru3 = new LRU({
47 | max: 1000,
48 | maxAge: 1
49 | })
50 | var lru3Counter = 0
51 |
52 | add(' set with `maxAge`', function() {
53 | lru3.set('key' + (lru3Counter++), 'value', 100000)
54 | })
55 |
56 | suite
57 | .on('cycle', (event) => {
58 | console.log(String(event.target))
59 | if (event.target.error)
60 | console.error(event.target.error)
61 | })
62 | .run();
63 |
--------------------------------------------------------------------------------
/test/benchmark-lru-map.js:
--------------------------------------------------------------------------------
1 | // https://github.com/isaacs/node-lru-cache/blob/master/benchmark/index.js
2 |
3 | 'use strict'
4 |
5 | console.log('\x1b[7m Benchmarking \x1b[1mlru-map \x1b[0m');
6 |
7 | var benchmark = require('benchmark')
8 |
9 | // function LRU() { const lru = new Map; lru.peek = lru.get; return lru; }
10 | var LRU = require('lru-map')
11 |
12 | var suite = new benchmark.Suite()
13 |
14 | function add(name, fn) {
15 | suite.add(name, fn)
16 | }
17 |
18 | // SET
19 | var lru1 = new LRU({
20 | maxSize: 1000
21 | })
22 | var lru1Counter = 0
23 |
24 | add(' set', function() {
25 | lru1.set('key' + (lru1Counter++), 'value')
26 | })
27 |
28 | // GET and PEEK
29 | var lru2 = new LRU({
30 | maxSize: 1000
31 | })
32 | var lru2Counter = 0
33 |
34 | for (var i = 0; i < 1000; i++)
35 | lru2.set('key' + i, 'value')
36 |
37 | add(' get', function() {
38 | lru2.get('key' + (lru2Counter++) % 1000)
39 | })
40 |
41 | add(' peek', function() {
42 | lru2.peek('key' + (lru2Counter++) % 1000)
43 | })
44 |
45 | // SET with maxAge
46 | var lru3 = new LRU({
47 | maxSize: 1000,
48 | maxAge: 1
49 | })
50 | var lru3Counter = 0
51 |
52 | add(' set with `maxAge`', function() {
53 | lru3.set('key' + (lru3Counter++), 'value', 100000)
54 | })
55 |
56 | suite
57 | .on('cycle', (event) => {
58 | console.log(String(event.target))
59 | if (event.target.error)
60 | console.error(event.target.error)
61 | })
62 | .run();
63 |
--------------------------------------------------------------------------------
/test/benchmark-lru.js:
--------------------------------------------------------------------------------
1 | // https://github.com/isaacs/node-lru-cache/blob/master/benchmark/index.js
2 |
3 | 'use strict'
4 |
5 | console.log('\x1b[7m Benchmarking \x1b[1mlru \x1b[0m');
6 |
7 | var benchmark = require('benchmark')
8 |
9 | // function LRU() { const lru = new Map; lru.peek = lru.get; return lru; }
10 | var LRU = require('lru')
11 |
12 | var suite = new benchmark.Suite()
13 |
14 | function add(name, fn) {
15 | suite.add(name, fn)
16 | }
17 |
18 | // SET
19 | var lru1 = new LRU({
20 | max: 1000
21 | })
22 | var lru1Counter = 0
23 |
24 | add(' set', function() {
25 | lru1.set('key' + (lru1Counter++), 'value')
26 | })
27 |
28 | // GET and PEEK
29 | var lru2 = new LRU({
30 | max: 1000
31 | })
32 | var lru2Counter = 0
33 |
34 | for (var i = 0; i < 1000; i++)
35 | lru2.set('key' + i, 'value')
36 |
37 | add(' get', function() {
38 | lru2.get('key' + (lru2Counter++) % 1000)
39 | })
40 |
41 | add(' peek', function() {
42 | lru2.peek('key' + (lru2Counter++) % 1000)
43 | })
44 |
45 | // SET with maxAge
46 | var lru3 = new LRU({
47 | max: 1000,
48 | maxAge: 1
49 | })
50 | var lru3Counter = 0
51 |
52 | add(' set with `maxAge`', function() {
53 | lru3.set('key' + (lru3Counter++), 'value', 100000)
54 | })
55 |
56 | suite
57 | .on('cycle', (event) => {
58 | console.log(String(event.target))
59 | if (event.target.error)
60 | console.error(event.target.error)
61 | })
62 | .run();
63 |
--------------------------------------------------------------------------------
/test/benchmark-quick-lru.js:
--------------------------------------------------------------------------------
1 | // https://github.com/isaacs/node-lru-cache/blob/master/benchmark/index.js
2 |
3 | 'use strict'
4 |
5 | console.log('\x1b[7m Benchmarking \x1b[1mquick-lru \x1b[0m');
6 |
7 | var benchmark = require('benchmark')
8 |
9 | // function LRU() { const lru = new Map; lru.peek = lru.get; return lru; }
10 | var LRU = require('quick-lru')
11 |
12 | var suite = new benchmark.Suite()
13 |
14 | function add(name, fn) {
15 | suite.add(name, fn)
16 | }
17 |
18 | // SET
19 | var lru1 = new LRU({
20 | maxSize: 1000
21 | })
22 | var lru1Counter = 0
23 |
24 | add(' set', function() {
25 | lru1.set('key' + (lru1Counter++), 'value')
26 | })
27 |
28 | // GET and PEEK
29 | var lru2 = new LRU({
30 | maxSize: 1000
31 | })
32 | var lru2Counter = 0
33 |
34 | for (var i = 0; i < 1000; i++)
35 | lru2.set('key' + i, 'value')
36 |
37 | add(' get', function() {
38 | lru2.get('key' + (lru2Counter++) % 1000)
39 | })
40 |
41 | add(' peek', function() {
42 | lru2.peek('key' + (lru2Counter++) % 1000)
43 | })
44 |
45 | // SET with maxAge
46 | var lru3 = new LRU({
47 | maxSize: 1000,
48 | maxAge: 1
49 | })
50 | var lru3Counter = 0
51 |
52 | add(' set with `maxAge`', function() {
53 | lru3.set('key' + (lru3Counter++), 'value', 100000)
54 | })
55 |
56 | suite
57 | .on('cycle', (event) => {
58 | console.log(String(event.target))
59 | if (event.target.error)
60 | console.error(event.target.error)
61 | })
62 | .run();
63 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | const LRU = require('../cjs');
2 |
3 | const sleep = ms => new Promise($ => setTimeout($, ms));
4 |
5 | const item1 = ['a', 1];
6 | const item2 = ['b', 2];
7 | const item3 = ['c', 3];
8 |
9 | const lru1 = new LRU(2);
10 | const lru2 = new LRU({max: 2});
11 | const lru3 = new LRU({maxSize: 2, maxAge: 200});
12 |
13 | console.assert(lru1.set(...item1) === lru1, 1);
14 | console.assert(lru1.get(item1[0]) === item1[1], 2);
15 | console.assert(lru1.set(...item2) === lru1, 3);
16 | console.assert(lru1.set(...item3) === lru1, 4);
17 |
18 | (async () => {
19 | await sleep(10);
20 | console.assert(lru1.get(item1[0]) === void 0, 5);
21 | console.assert(JSON.stringify([...lru1]) === JSON.stringify([item2, item3]), 6);
22 |
23 | lru1.forEach(Object);
24 | lru1.delete(item2[0]);
25 | lru1.forEach(function (value, key, map) {
26 | console.assert(this === lru2, 7);
27 | console.assert(map === lru1, 8);
28 | console.assert(key === item3[0], 9);
29 | console.assert(value === item3[1], 10);
30 | }, lru2);
31 |
32 | for (const [key, value] of lru1) {
33 | console.assert(key === item3[0], 11);
34 | console.assert(value === item3[1], 12);
35 | }
36 |
37 | for (const [key, value] of lru1.entries()) {
38 | console.assert(key === item3[0], 11);
39 | console.assert(value === item3[1], 12);
40 | }
41 |
42 | for (const value of lru1.values()) {
43 | console.assert(value === item3[1], 13);
44 | }
45 |
46 | console.assert(lru1.peek(item3[0]) === item3[1], 14);
47 |
48 | lru3.set(...item1).set(...item2);
49 |
50 | await sleep(100);
51 | lru3.set(...item3);
52 | await sleep(10);
53 | console.assert(JSON.stringify([...lru3]) === JSON.stringify([item2, item3]), 15);
54 |
55 | await sleep(150);
56 | lru3.set(...item1).set(...item3);
57 | await sleep(10);
58 | console.assert(JSON.stringify([...lru3]) === JSON.stringify([item3, item1]), 16);
59 |
60 | await sleep(250);
61 | console.assert(JSON.stringify([...lru3]) === '[]', 17);
62 | lru3.set(...item1).set(...item2);
63 |
64 | await sleep(50);
65 | lru3.set(...item3);
66 |
67 | await sleep(0);
68 | lru3.set(...item1);
69 | const lur4 = new LRU({maxAge: 100});
70 | console.assert(lur4.peek('any') === void 0, 18);
71 | lur4.set(...item1);
72 |
73 | await sleep(50);
74 | lur4.set(...item2).set(...item3);
75 |
76 | })();
77 |
--------------------------------------------------------------------------------