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.
54 lines
1.3 KiB
54 lines
1.3 KiB
var wrappy = require('wrappy') |
|
var reqs = Object.create(null) |
|
var once = require('once') |
|
|
|
module.exports = wrappy(inflight) |
|
|
|
function inflight (key, cb) { |
|
if (reqs[key]) { |
|
reqs[key].push(cb) |
|
return null |
|
} else { |
|
reqs[key] = [cb] |
|
return makeres(key) |
|
} |
|
} |
|
|
|
function makeres (key) { |
|
return once(function RES () { |
|
var cbs = reqs[key] |
|
var len = cbs.length |
|
var args = slice(arguments) |
|
|
|
// XXX It's somewhat ambiguous whether a new callback added in this |
|
// pass should be queued for later execution if something in the |
|
// list of callbacks throws, or if it should just be discarded. |
|
// However, it's such an edge case that it hardly matters, and either |
|
// choice is likely as surprising as the other. |
|
// As it happens, we do go ahead and schedule it for later execution. |
|
try { |
|
for (var i = 0; i < len; i++) { |
|
cbs[i].apply(null, args) |
|
} |
|
} finally { |
|
if (cbs.length > len) { |
|
// added more in the interim. |
|
// de-zalgo, just in case, but don't call again. |
|
cbs.splice(0, len) |
|
process.nextTick(function () { |
|
RES.apply(null, args) |
|
}) |
|
} else { |
|
delete reqs[key] |
|
} |
|
} |
|
}) |
|
} |
|
|
|
function slice (args) { |
|
var length = args.length |
|
var array = [] |
|
|
|
for (var i = 0; i < length; i++) array[i] = args[i] |
|
return array |
|
}
|
|
|