-
Notifications
You must be signed in to change notification settings - Fork 2
snippets
neonstalwart edited this page Jan 24, 2011
·
6 revisions
var req = 'req',
handler = {
addProcessor: function (processor) {
var handler = this,
process = this.process;
this.process = function (req) {
return Promise.when(process.call(handler, req), function (res) {
return processor(req, res);
});
};
},
process: function (req) {
return 'res';
}
},
processor1 = function (req , res) {
var dfd = new Promise.Deferred();
setTimeout(function () {
dfd.resolve(res + ' contribution1');
}, 500);
console.log('processor1', this, arguments);
return dfd.promise;
},
processor2 = function (req , res) {
var dfd = new Promise.Deferred();
setTimeout(function () {
dfd.resolve(res + ' contribution2');
}, 1500);
console.log('processor2', this, arguments);
return dfd.promise;
},
res;
handler.addProcessor(processor1);
handler.addProcessor(processor2);
res = handler.process(req);
console.log(res);
Promise.when(res, function (x) {
console.log(x);
});
this would be wrapped in a facility that read from the configuration and applied the Logger as needed. for example:
var logFacility = {
logger: new Logger(), // defined below
processModel: function (model) {
// if model says to add a logger then...
var prop = model.isInstance ? 'instance' : 'ctor';
model[prop] = this.logger.apply(model[prop], model.logger.selector, model.logger.advice);
}
};
var Ctor = Compose(function (foo) {
this.foo = foo;
}, {
bar: function () {
console.log('bar');
return 'bar function';
},
baz: function () {
console.log('baz');
return 'baz function';
},
boo: function () {
throw new Error('boo hoo...');
}
}),
obj = {
foo: function () {
console.log('foo');
}
},
// this is the interesting part, the rest is just some tests
Logger = Compose({
apply: function (obj, selector, advice) {
advice = typeof advice === 'function' ? {
after: advice
} : advice;
var mixin = {},
base = typeof obj === 'function' ? obj.prototype : obj,
composer = typeof obj === 'function' ? Compose : Compose.create,
prop;
// TODO: take selector into account when creating mixin
for (prop in base) {
if (base.hasOwnProperty(prop) /* && something with selector */) {
mixin[prop] = Compose.around(function (original) {
return function () {
var ret;
if (advice.before) {
advice.before.apply(this, arguments);
}
try {
ret = original.apply(this, arguments);
if (advice.afterReturning) {
advice.afterReturning.call(this, ret);
}
return ret;
}
catch (e) {
if (advice.afterThrowing) {
advice.afterThrowing.call(this, e);
}
// propogate the exception
throw e;
}
finally {
if (advice.after) {
advice.after.call(this);
}
}
}
});
}
}
return composer(obj, mixin);
}
}),
logger = new Logger();
console.log('before applying logger');
var b = new Ctor('xyz');
console.log(b.foo);
b.bar();
b.baz();
obj.foo();
console.log('applying function advice');
var Another = logger.apply(Ctor, null, function () {
console.log('function advice');
});
var obj2 = logger.apply(obj, null, function () {
console.log('function advice');
});
var c = new Another('bbb');
console.log(c.foo);
c.bar();
c.baz();
obj2.foo();
console.log('applying object advice');
var advice = {
before: function () {
console.log('before advice', this, arguments);
},
after: function () {
console.log('after advice', this, arguments);
},
afterReturning: function () {
console.log('after returning advice', this, arguments);
},
afterThrowing: function () {
console.log('after throwing advice', this, arguments);
}
};
var YetAnother = logger.apply(Ctor, null, advice),
obj3 = logger.apply(obj, null, advice);
var d = new YetAnother('xxx');
console.log(d.foo);
d.bar(2,3,4);
d.baz('dddd');
obj3.foo('??!??');
d.boo(':(');