Fullstack Conference - Proxies before proxies: The hidden gems of Javascript AOP
- 7. SCARLETJS
• API fluent interface
• Readability
• Performance
• Use of Core features
• Lack of ability to use common proxies
• Challenge
• And to have a little fun
- 10. called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
called awesomeoThing <Any Date> with [X,Y, Z] params executed in .00000001 ms
- 11. var awesomeoThing = function(x,y,z){
var startTime = new Date();
…
var endTime = new Date();
console.log(‘called awesomeoThing‘
+ new Date()
+ ’ with params:’
+ [x,y,z]
+ ’ executed in:’
+ endTime-startTime);
…
}
- 14. @Component
@Aspect
public class MyLogger{
@Around("execution(* com.my.messaging..*.*(..))")
public Object logAfterMethod(ProceedingJoinPoint joinPoint) throws Throwable {
Logger log = Logger.getLogger(joinPoint.getTarget().getClass());
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object retVal = joinPoint.proceed();
stopWatch.stop();
….
System.out.println(“called: “
+ joinPoint.getTarget().getClass().getName()
+ “ with args: “
+ args
+ “executed in: “
+ stopWatch.getTotalTimeMillis());
}
}
- 16. Var wrapper = function(){
var startTime = new Date();
var result = awesmeoThing();
var endTime = new Date();
console.log(‘called awesomeoThing‘
+ new Date()
+ ’ with params:’
+ [x,y,z]
+ ’ executed in:’
+ endTime-startTime);
return result;
}
- 17. var wrapper = function(){
var startTime = new Date();
var result = awesmeoThing();
var endTime = new Date();
console.log(‘called awesomeoThing‘
+ new Date()
+ ’ with params:’
+ x+y+z
+ ’ executed in:’
+ endTime-startTime);
return result;
}
var awesomeoThing = function(x,y,z){
var startTime = new Date();
…
var endTime = new Date();
console.log(‘called awesomeoThing‘
+ new Date()
+ ’ with params:’
+ x+y+z
+ ’ executed in:’
+ endTime-startTime);
…
}
- 19. WHAT’S OUT THERE
TODAY?
• Hooker by Ben Alman (Cowboy) (Author and
main contributor of grunt)
• “Monkey-Patch(hook) functions for debugging
and stuff” – Github Readme
• Hooks by Brian Noguchi(bnoguchi)
• “Add pre and post middleware hooks to your
JavaScript methods.”
- 21. HOOKJS
• create an instance of the thing
var instance = new awesemoThing();
• assign each member of the hooks implementation into the object
for(var k in hooks){
Instance[k] = hooks[k];
}
• Implement a method to implement before underlying method is called:
instance.pre(‘method’,function(next){
})
• Implement a post method to get called after the underlying method is called:
Instance.post(‘method’,function(next){
})
- 27. USE OF CORE
FEATURES
• No pre and post methods. Use real events
- 28. LACK OF ABILITY TO USE
COMMON PROXIES
• Easily be able to pull down and
use a logger, security module, etc
- 31. var purr = scarlet.plugins.purr;
purr.when(Math,'min').play();
Math.min(1,2,3);
- 35. TESTING
• Tools Used
• Mocha
• Builders
ScarletBuilder.forInstance(<AnyInstance>)
ScarletBuilder.forProperty(<AnyProperty>)
.withInterceptors(<ArrayOfInterceptors>);
ScarletBuilder.forMethod(<AnyMethod>)
.withParameters(<AnyParams>)
.withEvents(<AnyEvents>)
.Assert();
- 37. MAKING IT EASY
• Intercept a function, object, or property
• Define event listeners for before and after the
intercepted function had been called
• Define multiple functions to do the
interception
• Being able to chain method calls together and
have a fluent interface
- 43. var someProxy = Scarlet.intercept(<ANYFUNCTION>)
.using(<INTERCEPTOR_FUNCTION>)
.proxy();
- 44. Var awesemeoThing = function(){}
var someProxy = Scarlet.intercept(awesemeoThing)
.using(function(info, proceed){
var startTime = new Date();
var result = proceed();
var endTime = new Date();
console.log(‘called ‘ +info.methodName
+ new Date()
+ ’ with params:’
+ [x,y,z]
+ ’ executed in:’
+ endTime-startTime);
})
.proxy();
- 49. function MyObjectB(myObjectA){
};
scarlet.plugins.ioc
.register("myObjectA", MyObjectA)
.register("myObjectB", MyObjectB);
var myObjectB = scarlet
.plugins
.ioc
.resolve("myObjectB");
myObjectB.anyMethod();
- 51. ES6 - PROXIES
”A proxy object is an exotic object whose essential
internal methods are partially implemented using ECMAScript
code” – ES6 Draft October 2014
- 52. var awesemeoFunction = function(){…};
var proxiedObject = new Proxy(awesemeoFunction,{
apply: function(target, receiver, args){
var startTime = new Date();
var result = target(args);
var endTime = new Date();
console.log(‘called awesomeThing‘
+ new Date()
+ ’ with params:’
+ args
+ ’ executed in:’
+ endTime-startTime);
return result;
}
});
- 53. var awesemeoThing= {};
var proxiedThing = new Proxy(awesemeoThing,{
get: function(target, name){
console.log("In Get Proxy");
return target[name];
}
});
var x = proxiedThing.any;
- 54. var awesemeoThing= {};
var proxiedThing = new Proxy(awesemeoThing,{
set: function(target, name, value){
console.log("In Set Proxy");
target[name] = value;
}
});
proxiedThing.any = 'thing';
- 55. NODE.JS PROXIES
• Proxies can be enabled using the following commands:
• $ node –harmony-proxies
• $ node --harmony
- 57. HARMONY-REFLECT
• Shim so that the current draft implementation of proxies can be
used https://github.com/tvcutsem/harmony-reflect
1. Install the module:
• npm install harmony-reflect
2. Require at the top of your js file:
• require(‘harmony-reflect);
3. Run node in harmony mode:
• $ node --harmony
- 60. var negativeArray = require('negative-array');
var unicorn = negativeArray(['pony',
'cake',
'rainbow']);
console.log(unicorn[-1]);
- 61. module.exports = function (arr) {
…
return new Proxy(arr, {
get: function (target, name) {
var i = +name;
return target[i < 0 ?
target.length + i :
i];
},
}
- 62. ANNOTATIONS
• Traceur – Converts ES6 to ES5 runnable code
• https://github.com/google/traceur-compiler
• Install through npm
• Npm install traceur
• Allows for annotations to be used with the
following flags:
• traceur <ANY_FILE> --annotations true
- 64. …
var AnyAnnotation = function() {};
function simpleFunction() {
return 'any';
}
Object.defineProperty(simpleFunction,
"annotations",
{
get: function() {
return [new AnyAnnotation];
}
});
- 67. var Logger = function(){
return function( target, receiver, args) {
var startTime = new Date();
var result = target(args);
var endTime = new Date();
console.log(‘called ‘ + target.name
+ new Date()
+ ’ with params:’
+ args
+ ’ executed in:’
+ endTime-startTime);
return result;
};
};
- 68. var createProxy = function(anyFunction){
return new Proxy(anyFunction,
{
apply : anyFunction.
annotations[0]
});
};
simpleFunction = createProxy(simpleFunction);
simpleFunction();
- 71. THANK YOU
• @timchaplin
• https://github.com/tjchaplin
- 72. REFERENCES
• http://soft.vub.ac.be/~tvcutsem/invokedynamic/proxies_tut
orial
• https://brendaneich.com/2012/10/harmony-of-dreams-come-
true/
• http://wiki.ecmascript.org/doku.php?id=harmony:specifica
tion_drafts
• http://dailyjs.com/2013/11/15/negative-array/
• https://github.com/sindresorhus/negative-array/
blob/master/package.json
• https://github.com/tvcutsem/proxy-handlers
• https://github.com/JustinDrake/node-es6-
examples#proxies