max-age.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* eslint consistent-this: 0 */
  2. // Timeout cached values
  3. "use strict";
  4. var aFrom = require("es5-ext/array/from")
  5. , forEach = require("es5-ext/object/for-each")
  6. , nextTick = require("next-tick")
  7. , isPromise = require("is-promise")
  8. , timeout = require("timers-ext/valid-timeout")
  9. , extensions = require("../lib/registered-extensions");
  10. var noop = Function.prototype, max = Math.max, min = Math.min, create = Object.create;
  11. extensions.maxAge = function (maxAge, conf, options) {
  12. var timeouts, postfix, preFetchAge, preFetchTimeouts;
  13. maxAge = timeout(maxAge);
  14. if (!maxAge) return;
  15. timeouts = create(null);
  16. postfix =
  17. (options.async && extensions.async) || (options.promise && extensions.promise)
  18. ? "async"
  19. : "";
  20. conf.on("set" + postfix, function (id) {
  21. timeouts[id] = setTimeout(function () {
  22. conf.delete(id);
  23. }, maxAge);
  24. if (typeof timeouts[id].unref === "function") timeouts[id].unref();
  25. if (!preFetchTimeouts) return;
  26. if (preFetchTimeouts[id]) {
  27. if (preFetchTimeouts[id] !== "nextTick") clearTimeout(preFetchTimeouts[id]);
  28. }
  29. preFetchTimeouts[id] = setTimeout(function () {
  30. delete preFetchTimeouts[id];
  31. }, preFetchAge);
  32. if (typeof preFetchTimeouts[id].unref === "function") preFetchTimeouts[id].unref();
  33. });
  34. conf.on("delete" + postfix, function (id) {
  35. clearTimeout(timeouts[id]);
  36. delete timeouts[id];
  37. if (!preFetchTimeouts) return;
  38. if (preFetchTimeouts[id] !== "nextTick") clearTimeout(preFetchTimeouts[id]);
  39. delete preFetchTimeouts[id];
  40. });
  41. if (options.preFetch) {
  42. if (options.preFetch === true || isNaN(options.preFetch)) {
  43. preFetchAge = 0.333;
  44. } else {
  45. preFetchAge = max(min(Number(options.preFetch), 1), 0);
  46. }
  47. if (preFetchAge) {
  48. preFetchTimeouts = {};
  49. preFetchAge = (1 - preFetchAge) * maxAge;
  50. conf.on("get" + postfix, function (id, args, context) {
  51. if (!preFetchTimeouts[id]) {
  52. preFetchTimeouts[id] = "nextTick";
  53. nextTick(function () {
  54. var result;
  55. if (preFetchTimeouts[id] !== "nextTick") return;
  56. delete preFetchTimeouts[id];
  57. conf.delete(id);
  58. if (options.async) {
  59. args = aFrom(args);
  60. args.push(noop);
  61. }
  62. result = conf.memoized.apply(context, args);
  63. if (options.promise) {
  64. // Supress eventual error warnings
  65. if (isPromise(result)) {
  66. if (typeof result.done === "function") result.done(noop, noop);
  67. else result.then(noop, noop);
  68. }
  69. }
  70. });
  71. }
  72. });
  73. }
  74. }
  75. conf.on("clear" + postfix, function () {
  76. forEach(timeouts, function (id) {
  77. clearTimeout(id);
  78. });
  79. timeouts = {};
  80. if (preFetchTimeouts) {
  81. forEach(preFetchTimeouts, function (id) {
  82. if (id !== "nextTick") clearTimeout(id);
  83. });
  84. preFetchTimeouts = {};
  85. }
  86. });
  87. };