You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.6 KiB

  1. /*
  2. ## Purpose
  3. To avoid running expensive IO or computation concurrently.
  4. If the result of IO or computation is requested while an identical request
  5. is already in progress, wait until the first one completes and provide its
  6. result to every routine that requested it.
  7. Asynchrony is guaranteed.
  8. ## Usage
  9. Provide:
  10. 1. a named key for the computation or resource,
  11. 2. a callback to handle the result
  12. 3. an implementation which calls back with the result
  13. ```
  14. var batch = Batch();
  15. var read = function (path, cb) {
  16. batch(path, cb, function (done) {
  17. console.log("reading %s", path);
  18. fs.readFile(path, 'utf8', done);
  19. });
  20. };
  21. read('./pewpew.txt', function (err, data) {
  22. if (err) { return void console.error(err); }
  23. console.log(data);
  24. });
  25. read('./pewpew.txt', function (err, data) {
  26. if (err) { return void console.error(err); }
  27. console.log(data);
  28. });
  29. ```
  30. */
  31. module.exports = function (/* task */) {
  32. var map = {};
  33. return function (id, cb, impl) {
  34. if (typeof(cb) !== 'function' || typeof(impl) !== 'function') {
  35. throw new Error("expected callback and implementation");
  36. }
  37. if (map[id]) { return void map[id].push(cb); }
  38. map[id] = [cb];
  39. impl(function () {
  40. var args = Array.prototype.slice.call(arguments);
  41. //if (map[id] && map[id].length > 1) { console.log("BATCH-READ DID ITS JOB for [%s][%s]", task, id); }
  42. setTimeout(function () {
  43. map[id].forEach(function (h) {
  44. h.apply(null, args);
  45. });
  46. delete map[id];
  47. });
  48. });
  49. };
  50. };