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