max-age.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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 () { conf.delete(id); }, maxAge);
  22. if (typeof timeouts[id].unref === "function") timeouts[id].unref();
  23. if (!preFetchTimeouts) return;
  24. if (preFetchTimeouts[id]) {
  25. if (preFetchTimeouts[id] !== "nextTick") clearTimeout(preFetchTimeouts[id]);
  26. }
  27. preFetchTimeouts[id] = setTimeout(function () {
  28. delete preFetchTimeouts[id];
  29. }, preFetchAge);
  30. if (typeof preFetchTimeouts[id].unref === "function") preFetchTimeouts[id].unref();
  31. });
  32. conf.on("delete" + postfix, function (id) {
  33. clearTimeout(timeouts[id]);
  34. delete timeouts[id];
  35. if (!preFetchTimeouts) return;
  36. if (preFetchTimeouts[id] !== "nextTick") clearTimeout(preFetchTimeouts[id]);
  37. delete preFetchTimeouts[id];
  38. });
  39. if (options.preFetch) {
  40. if (options.preFetch === true || isNaN(options.preFetch)) {
  41. preFetchAge = 0.333;
  42. } else {
  43. preFetchAge = max(min(Number(options.preFetch), 1), 0);
  44. }
  45. if (preFetchAge) {
  46. preFetchTimeouts = {};
  47. preFetchAge = (1 - preFetchAge) * maxAge;
  48. conf.on("get" + postfix, function (id, args, context) {
  49. if (!preFetchTimeouts[id]) {
  50. preFetchTimeouts[id] = "nextTick";
  51. nextTick(function () {
  52. var result;
  53. if (preFetchTimeouts[id] !== "nextTick") return;
  54. delete preFetchTimeouts[id];
  55. conf.delete(id);
  56. if (options.async) {
  57. args = aFrom(args);
  58. args.push(noop);
  59. }
  60. result = conf.memoized.apply(context, args);
  61. if (options.promise) {
  62. // Supress eventual error warnings
  63. if (isPromise(result)) {
  64. if (typeof result.done === "function") result.done(noop, noop);
  65. else result.then(noop, noop);
  66. }
  67. }
  68. });
  69. }
  70. });
  71. }
  72. }
  73. conf.on("clear" + postfix, function () {
  74. forEach(timeouts, function (id) { clearTimeout(id); });
  75. timeouts = {};
  76. if (preFetchTimeouts) {
  77. forEach(preFetchTimeouts, function (id) { if (id !== "nextTick") clearTimeout(id); });
  78. preFetchTimeouts = {};
  79. }
  80. });
  81. };