memoize.js 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = memoize;
  6. var _identity = require('lodash/identity');
  7. var _identity2 = _interopRequireDefault(_identity);
  8. var _slice = require('./internal/slice');
  9. var _slice2 = _interopRequireDefault(_slice);
  10. var _setImmediate = require('./internal/setImmediate');
  11. var _setImmediate2 = _interopRequireDefault(_setImmediate);
  12. var _initialParams = require('./internal/initialParams');
  13. var _initialParams2 = _interopRequireDefault(_initialParams);
  14. var _wrapAsync = require('./internal/wrapAsync');
  15. var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
  16. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  17. function has(obj, key) {
  18. return key in obj;
  19. }
  20. /**
  21. * Caches the results of an async function. When creating a hash to store
  22. * function results against, the callback is omitted from the hash and an
  23. * optional hash function can be used.
  24. *
  25. * If no hash function is specified, the first argument is used as a hash key,
  26. * which may work reasonably if it is a string or a data type that converts to a
  27. * distinct string. Note that objects and arrays will not behave reasonably.
  28. * Neither will cases where the other arguments are significant. In such cases,
  29. * specify your own hash function.
  30. *
  31. * The cache of results is exposed as the `memo` property of the function
  32. * returned by `memoize`.
  33. *
  34. * @name memoize
  35. * @static
  36. * @memberOf module:Utils
  37. * @method
  38. * @category Util
  39. * @param {AsyncFunction} fn - The async function to proxy and cache results from.
  40. * @param {Function} hasher - An optional function for generating a custom hash
  41. * for storing results. It has all the arguments applied to it apart from the
  42. * callback, and must be synchronous.
  43. * @returns {AsyncFunction} a memoized version of `fn`
  44. * @example
  45. *
  46. * var slow_fn = function(name, callback) {
  47. * // do something
  48. * callback(null, result);
  49. * };
  50. * var fn = async.memoize(slow_fn);
  51. *
  52. * // fn can now be used as if it were slow_fn
  53. * fn('some name', function() {
  54. * // callback
  55. * });
  56. */
  57. function memoize(fn, hasher) {
  58. var memo = Object.create(null);
  59. var queues = Object.create(null);
  60. hasher = hasher || _identity2.default;
  61. var _fn = (0, _wrapAsync2.default)(fn);
  62. var memoized = (0, _initialParams2.default)(function memoized(args, callback) {
  63. var key = hasher.apply(null, args);
  64. if (has(memo, key)) {
  65. (0, _setImmediate2.default)(function () {
  66. callback.apply(null, memo[key]);
  67. });
  68. } else if (has(queues, key)) {
  69. queues[key].push(callback);
  70. } else {
  71. queues[key] = [callback];
  72. _fn.apply(null, args.concat(function () /*args*/{
  73. var args = (0, _slice2.default)(arguments);
  74. memo[key] = args;
  75. var q = queues[key];
  76. delete queues[key];
  77. for (var i = 0, l = q.length; i < l; i++) {
  78. q[i].apply(null, args);
  79. }
  80. }));
  81. }
  82. });
  83. memoized.memo = memo;
  84. memoized.unmemoized = fn;
  85. return memoized;
  86. }
  87. module.exports = exports['default'];