|
process.addAsyncListener = addAsyncListener; |
|
var listeners = []; |
|
|
|
// Wrap some easy event sources to test things out |
|
setTimeout = wrapFirst(setTimeout); |
|
setImmediate = wrapFirst(setImmediate); |
|
setInterval = wrapFirst(setInterval); |
|
process.nextTick = wrapFirst(process.nextTick); |
|
process.nextTick = wrapFirst(process.nextTick); |
|
var fs = require('fs'); |
|
fs.stat = wrapLast(fs.stat); |
|
|
|
function addAsyncListener(onAsync, callbackObject) { |
|
listeners.push({ |
|
onAsync: onAsync, |
|
callbackObject: callbackObject |
|
}); |
|
} |
|
|
|
function wrapFirst(fn) { |
|
return function () { |
|
if (typeof arguments[0] === "function") { |
|
arguments[0] = wrapCallback(arguments[0]); |
|
} |
|
return fn.apply(this, arguments); |
|
}; |
|
} |
|
|
|
function wrapLast(fn) { |
|
return function () { |
|
var index = arguments.length - 1; |
|
if (typeof arguments[index] === "function") { |
|
arguments[index] = wrapCallback(arguments[index]); |
|
} |
|
return fn.apply(this, arguments); |
|
} |
|
} |
|
|
|
function wrapCallback(original) { |
|
var list = Array.prototype.slice.call(listeners); |
|
var length = list.length; |
|
var hasAny = false, hasErr = false; |
|
for (var i = 0; i < length; ++i) { |
|
var obj = list[i].callbackObject; |
|
if (obj) { |
|
hasAny = true; |
|
if (obj.error) hasErr = true; |
|
} |
|
} |
|
return hasAny ? hasErr ? catchyWrap(original, list, length) |
|
: normalWrap(original, list, length) |
|
: noWrap(original, list, length); |
|
} |
|
|
|
function catchyWrap(original, list, length) { |
|
var data = new Array(length); |
|
for (var i = 0; i < length; ++i) { |
|
var listener = list[i]; |
|
data[i] = listener.onAsync(); |
|
} |
|
return function () { |
|
var i, obj; |
|
for (var i = 0; i < length; ++i) { |
|
obj = list[i].callbackObject; |
|
if (obj && obj.before) obj.before(data[i]); |
|
} |
|
try { |
|
return original.apply(this, arguments); |
|
} |
|
catch (err) { |
|
for (i = 0; i < length; ++i) { |
|
obj = list[i].callbackObject; |
|
if (obj && obj.after) obj.after(data[i]); |
|
} |
|
} |
|
finally { |
|
for (i = 0; i < length; ++i) { |
|
obj = list[i].callbackObject; |
|
if (obj && obj.after) obj.after(data[i]); |
|
} |
|
for (i = 0; i < length; ++i) { |
|
obj = list[i].callbackObject; |
|
if (obj && obj.done) obj.done(data[i]); |
|
} |
|
} |
|
} |
|
} |
|
|
|
function normalWrap(original, list, length) { |
|
var data = new Array(length); |
|
for (var i = 0; i < length; ++i) { |
|
var listener = list[i]; |
|
data[i] = listener.onAsync(); |
|
} |
|
return function () { |
|
var i, obj; |
|
for (var i = 0; i < length; ++i) { |
|
obj = list[i].callbackObject; |
|
if (obj && obj.before) obj.before(data[i]); |
|
} |
|
try { |
|
return original.apply(this, arguments); |
|
} |
|
finally { |
|
for (i = 0; i < length; ++i) { |
|
obj = list[i].callbackObject; |
|
if (obj && obj.after) obj.after(data[i]); |
|
} |
|
for (i = 0; i < length; ++i) { |
|
obj = list[i].callbackObject; |
|
if (obj && obj.done) obj.done(data[i]); |
|
} |
|
} |
|
} |
|
} |
|
|
|
function noWrap(original, list, length) { |
|
for (var i = 0; i < length; ++i) { |
|
list[i].onAsync(); |
|
} |
|
return original; |
|
} |
|
|