/* eslint consistent-this: 0 */ // Timeout cached values "use strict"; var aFrom = require("es5-ext/array/from") , forEach = require("es5-ext/object/for-each") , nextTick = require("next-tick") , isPromise = require("is-promise") , timeout = require("timers-ext/valid-timeout") , extensions = require("../lib/registered-extensions"); var noop = Function.prototype, max = Math.max, min = Math.min, create = Object.create; extensions.maxAge = function (maxAge, conf, options) { var timeouts, postfix, preFetchAge, preFetchTimeouts; maxAge = timeout(maxAge); if (!maxAge) return; timeouts = create(null); postfix = (options.async && extensions.async) || (options.promise && extensions.promise) ? "async" : ""; conf.on("set" + postfix, function (id) { timeouts[id] = setTimeout(function () { conf.delete(id); }, maxAge); if (typeof timeouts[id].unref === "function") timeouts[id].unref(); if (!preFetchTimeouts) return; if (preFetchTimeouts[id]) { if (preFetchTimeouts[id] !== "nextTick") clearTimeout(preFetchTimeouts[id]); } preFetchTimeouts[id] = setTimeout(function () { delete preFetchTimeouts[id]; }, preFetchAge); if (typeof preFetchTimeouts[id].unref === "function") preFetchTimeouts[id].unref(); }); conf.on("delete" + postfix, function (id) { clearTimeout(timeouts[id]); delete timeouts[id]; if (!preFetchTimeouts) return; if (preFetchTimeouts[id] !== "nextTick") clearTimeout(preFetchTimeouts[id]); delete preFetchTimeouts[id]; }); if (options.preFetch) { if (options.preFetch === true || isNaN(options.preFetch)) { preFetchAge = 0.333; } else { preFetchAge = max(min(Number(options.preFetch), 1), 0); } if (preFetchAge) { preFetchTimeouts = {}; preFetchAge = (1 - preFetchAge) * maxAge; conf.on("get" + postfix, function (id, args, context) { if (!preFetchTimeouts[id]) { preFetchTimeouts[id] = "nextTick"; nextTick(function () { var result; if (preFetchTimeouts[id] !== "nextTick") return; delete preFetchTimeouts[id]; conf.delete(id); if (options.async) { args = aFrom(args); args.push(noop); } result = conf.memoized.apply(context, args); if (options.promise) { // Supress eventual error warnings if (isPromise(result)) { if (typeof result.done === "function") result.done(noop, noop); else result.then(noop, noop); } } }); } }); } } conf.on("clear" + postfix, function () { forEach(timeouts, function (id) { clearTimeout(id); }); timeouts = {}; if (preFetchTimeouts) { forEach(preFetchTimeouts, function (id) { if (id !== "nextTick") clearTimeout(id); }); preFetchTimeouts = {}; } }); };