I want to insert on pre execute and post execute hooks on functions in javascript classes.
Lets say I have a class like this.
class Foo {
method1(p1, p2) {
this.p1 = p1;
this.p2 = p2;
}
method2(p3) {
this.p3 = p3;
}
}
I want to define a before and after hook for these preexisting class methods. Something like this.
class Foo {
before(funName, ...params){
// Should print ('method1', [p1, p2]) when method 1 is called
// and ('method2', [p3]) when method 2 is called
console.log(funName, params)
}
after(funName, result){
// Should print the function name followed by its result
console.log(funName, result)
}
method1(p1, p2) {
this.p1 = p1;
this.p2 = p2;
}
method2(p3) {
this.p3 = p3;
}
}
export default Foo;
What is the best way of implementing these hooks with minimal changes in existing code?
Here is a rough solution to the problem:
// we iterate over all method names
Object.getOwnPropertyNames(Foo.prototype).forEach((name) => {
// First to do: we save the original method. Adding it to prototype
// is a good idea, we keep 'method1' as '_method1' and so on
Foo.prototype['_' + name] = Foo.prototype[name];
// Next, we replace the original method with one that does the logging
// before and after method execution.
Foo.prototype[name] = function() {
// all arguments that the method receives are in the 'arguments' object
console.log(`Method call: method1(${Object.values(arguments).join(', ')})`);
// now we call the original method, _method1, on this with all arguments we received
// this is probably the most confusing line of code here ;)
// (I never user this['method'] before - but it works)
const result = this['_' + name](...arguments);
// here is the post-execution logging
console.log(`Method result: ${result}`);
// and we need to return the original result of the method
return result;
};
});
Please note that this code is not part of the class itself, execute it as a normal script.
And there is a good chance that this short proof of concept crashes on real-world classes and requires some additional checks and special-case handlers, especially to get proper logging output. But it works with you Foo class.
Here's the working example: https://codesandbox.io/s/great-fog-c803c