inflight.js 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. var wrappy = require('wrappy')
  2. var reqs = Object.create(null)
  3. var once = require('once')
  4. module.exports = wrappy(inflight)
  5. function inflight (key, cb) {
  6. if (reqs[key]) {
  7. reqs[key].push(cb)
  8. return null
  9. } else {
  10. reqs[key] = [cb]
  11. return makeres(key)
  12. }
  13. }
  14. function makeres (key) {
  15. return once(function RES () {
  16. var cbs = reqs[key]
  17. var len = cbs.length
  18. var args = slice(arguments)
  19. // XXX It's somewhat ambiguous whether a new callback added in this
  20. // pass should be queued for later execution if something in the
  21. // list of callbacks throws, or if it should just be discarded.
  22. // However, it's such an edge case that it hardly matters, and either
  23. // choice is likely as surprising as the other.
  24. // As it happens, we do go ahead and schedule it for later execution.
  25. try {
  26. for (var i = 0; i < len; i++) {
  27. cbs[i].apply(null, args)
  28. }
  29. } finally {
  30. if (cbs.length > len) {
  31. // added more in the interim.
  32. // de-zalgo, just in case, but don't call again.
  33. cbs.splice(0, len)
  34. process.nextTick(function () {
  35. RES.apply(null, args)
  36. })
  37. } else {
  38. delete reqs[key]
  39. }
  40. }
  41. })
  42. }
  43. function slice (args) {
  44. var length = args.length
  45. var array = []
  46. for (var i = 0; i < length; i++) array[i] = args[i]
  47. return array
  48. }