const ttl = 1000; // ms
const avgKey = Symbol('average');
const lenKey = Symbol('length');
const getMymap = () =>
new Proxy(
{},
{
set(obj, prop, value) {
// average calc
const recalcAverage = (reverse = false) => {
const avg = obj[avgKey] || 0;
const len = obj[lenKey] || 0;
if (reverse) {
obj[lenKey] = Math.max(len - 1, 0);
obj[avgKey] = obj[lenKey] ? (avg * len - value) / obj[lenKey] : 0;
} else {
if (obj.hasOwnProperty(prop)) {
obj[avgKey] = ((avg - 1) * len + value) / len;
} else {
obj[avgKey] = (avg * len + value) / (len + 1);
obj[lenKey] = len + 1;
}
}
};
recalcAverage();
// ttl
setTimeout(() => {
delete obj[prop];
recalcAverage(true);
}, ttl);
obj[prop] = value;
return obj;
},
},
);
describe('mymap', () => {
it('should set key value', () => {
const mymap = getMymap();
mymap.abc = 2;
expect(mymap.abc).toBe(2);
});
it('should calc average', () => {
jest.useFakeTimers();
const mymap = getMymap();
mymap.abc = 2;
jest.advanceTimersByTime(500);
mymap.cde = 3;
expect(mymap[avgKey]).toBe(2.5);
jest.advanceTimersByTime(500);
expect(mymap[avgKey]).toBe(3);
jest.advanceTimersByTime(500);
expect(mymap[avgKey]).toBe(0);
});
it('should calc len', () => {
jest.useFakeTimers();
const mymap = getMymap();
mymap.abc = 2;
mymap.cde = 3;
expect(mymap[lenKey]).toBe(2);
});
});