index.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 'use strict';
  2. class LRU {
  3. constructor(max) {
  4. this.max = max;
  5. this.size = 0;
  6. this.cache = new Map();
  7. this._cache = new Map();
  8. }
  9. get(key, options) {
  10. let item = this.cache.get(key);
  11. const maxAge = options && options.maxAge;
  12. // only call Date.now() when necessary
  13. let now;
  14. function getNow() {
  15. now = now || Date.now();
  16. return now;
  17. }
  18. if (item) {
  19. // check expired
  20. if (item.expired && getNow() > item.expired) {
  21. item.expired = 0;
  22. item.value = undefined;
  23. } else {
  24. // update expired in get
  25. if (maxAge !== undefined) {
  26. const expired = maxAge ? getNow() + maxAge : 0;
  27. item.expired = expired;
  28. }
  29. }
  30. return item.value;
  31. }
  32. // try to read from _cache
  33. item = this._cache.get(key);
  34. if (item) {
  35. // check expired
  36. if (item.expired && getNow() > item.expired) {
  37. item.expired = 0;
  38. item.value = undefined;
  39. } else {
  40. // not expired, save to cache
  41. this._update(key, item);
  42. // update expired in get
  43. if (maxAge !== undefined) {
  44. const expired = maxAge ? getNow() + maxAge : 0;
  45. item.expired = expired;
  46. }
  47. }
  48. return item.value;
  49. }
  50. }
  51. set(key, value, options) {
  52. const maxAge = options && options.maxAge;
  53. const expired = maxAge ? Date.now() + maxAge : 0;
  54. let item = this.cache.get(key);
  55. if (item) {
  56. item.expired = expired;
  57. item.value = value;
  58. } else {
  59. item = {
  60. value,
  61. expired,
  62. };
  63. this._update(key, item);
  64. }
  65. }
  66. keys() {
  67. const cacheKeys = new Set();
  68. const now = Date.now();
  69. for (const entry of this.cache.entries()) {
  70. checkEntry(entry);
  71. }
  72. for (const entry of this._cache.entries()) {
  73. checkEntry(entry);
  74. }
  75. function checkEntry(entry) {
  76. const key = entry[0];
  77. const item = entry[1];
  78. if (entry[1].value && (!entry[1].expired) || item.expired >= now) {
  79. cacheKeys.add(key);
  80. }
  81. }
  82. return Array.from(cacheKeys.keys());
  83. }
  84. _update(key, item) {
  85. this.cache.set(key, item);
  86. this.size++;
  87. if (this.size >= this.max) {
  88. this.size = 0;
  89. this._cache = this.cache;
  90. this.cache = new Map();
  91. }
  92. }
  93. }
  94. module.exports = LRU;