29

Which Javascript AOP library do you use, and what are its key features ?

asked Jun 17, 2009 at 7:01

3 Answers 3

30

Here is what I found until now :

  • dotvoid's implementation, clean syntax, nice to use, the article is a good introduction on why/how to use the given code, supports introductions, but is bugged,
  • Dojo has what seems to be a good built-in implementation in dojox, here is a nice introduction on how to use it,
  • there is a plugin for jQuery, jquery-aop, with a rougher syntax, passing objects and methods in a javascript object,
  • AspectJS with an even rougher syntax (need to pass type of pointcut as arguments to a single method)

Like I said, dotvoid's code did not work. I corrected a little and got something that seems to work better :

InvalidAspect = new Error("Missing a valid aspect. Aspect is not a function.");
InvalidObject = new Error("Missing valid object or an array of valid objects.");
InvalidMethod = new Error("Missing valid method to apply aspect on.");
function doBefore(beforeFunc,func){
 return function(){
 beforeFunc.apply(this,arguments);
 return func.apply(this,arguments);
 }; 
}
function doAfter(func, afterFunc){
 return function(){
 var res = func.apply(this,arguments);
 afterFunc.apply(this,arguments);
 return res; 
 };
}
Aspects = function(){};
Aspects.prototype={
 _addIntroduction : function(intro, obj){
 for (var m in intro.prototype) {
 obj.prototype[m] = intro.prototype[m];
 }
 },
 addIntroduction : function(aspect, objs){
 var oType = typeof(objs);
 if (typeof(aspect) != 'function')
 throw(InvalidAspect);
 if (oType == 'function'){
 this._addIntroduction(aspect, objs);
 }
 else if (oType == 'object'){
 for (var n = 0; n < objs.length; n++){
 this._addIntroduction(aspect, objs[n]);
 }
 }
 else{
 throw InvalidObject;
 }
 },
 addBefore : function(aspect, obj, funcs){
 var fType = typeof(funcs);
 if (typeof(aspect) != 'function')
 throw(InvalidAspect);
 if (fType != 'object')
 funcs = Array(funcs);
 for (var n = 0; n < funcs.length; n++){
 var fName = funcs[n];
 var old = obj.prototype[fName];
 if (!old)
 throw InvalidMethod;
 var res = doBefore(aspect,old)
 obj.prototype[fName] = res;
 }
 },
 addAfter : function(aspect, obj, funcs) {
 if (typeof(aspect) != 'function')
 throw InvalidAspect;
 if (typeof(funcs) != 'object')
 funcs = Array(funcs);
 for (var n = 0; n < funcs.length; n++)
 {
 var fName = funcs[n];
 var old = obj.prototype[fName];
 if (!old)
 throw InvalidMethod;
 var res = doAfter(old,aspect);
 obj.prototype[fName] = res;
 }
 },
 addAround : function(aspect, obj, funcs){
 if (typeof(aspect) != 'function')
 throw InvalidAspect;
 if (typeof(funcs) != 'object')
 funcs = Array(funcs);
 for (var n = 0; n < funcs.length; n++)
 {
 var fName = funcs[n];
 var old = obj.prototype[fName];
 if (!old)
 throw InvalidMethod;
 var res = aspect(old);
 obj.prototype[fName] = res;
 }
 return true;
 }
}
answered Jun 17, 2009 at 8:00
Sign up to request clarification or add additional context in comments.

3 Comments

Does the code somehow work in Internet Explorer? As my tests failed, I googled around and it seems that IE doesn't have a "prototype"-property...
I've been running tests on this on IE7. Works fine. Lower versions untested though.
2014: I found this still very active framework jsAspect it seems to do what a AOP should do!
13

Have you seen meld.js and aop.js from https://github.com/cujojs?

SpringSource provides AOP functionality there, in addition to a bunch of other useful things for advanced Javascript programmers.

Disclaimer: I work for SpringSource.

Alex Chamberlain
4,2272 gold badges25 silver badges52 bronze badges
answered Jan 30, 2013 at 21:19

1 Comment

It's quite an old question... but thanks for the addition.
3

Based on dotvoid solution, I created my own version of JS AOP for my own projects needs. I basically want to minimize the aspect setup costs, so I added aspect setup functionality at Function.prototype.

Function.prototype.applyBefore = function (aspect, targetFuncNames) {
....
}

I also need to support aync callbacks, such as supporting authentication and authorization for certain methods. For example:

var authenticateAspect = function (error, success, context, args) {
 logger.log('authenticate (applyBefore async) aspect is being called');
 var request = $.ajax({
 url: "http://localhost/BlogWeb/api/user/authenticate",
 type: "GET",
 data: { username:'jeff', pwd:'jeff' },
 success: function (data) {
 if (data) {
 success();
 } else {
 error();
 }
 },
 error: error
 });
 return request;
};
Person.applyBefore(authenticateAspect, 'sendNotification');
var p1 = new Person();
p1.sendNotification();

To implement this, I need to run the security and and continue upon success or stop execution on failure.

var invalidAspect = new Error("Missing a valid aspect. Aspect is not a function."),
 invalidMethod = new Error("Missing valid method to apply aspect on.");
///Parameters: aspect - defines the methods we want call before or/and 
/// after each method call ob target obejct
/// targetFuncNames - target function names to apply aspects
///Return: it should return a new object with all aspects setup on target object
Function.prototype.applyBefore = function (aspect, targetFuncNames) {
 if (typeof (aspect) != 'function')
 throw invalidAspect;
 if (typeof (targetFuncNames) != 'object')
 targetFuncNames = Array(targetFuncNames);
 var targetObj = this;
 //error handling function
 // Copy the properties over onto the new prototype
 for (var i = 0, len = targetFuncNames.length; i < len; i++) {
 var funcName = targetFuncNames[i];
 var targetFunc = targetObj.prototype[funcName];
 if (!targetFunc)
 throw invalidMethod;
 targetObj.prototype[funcName] = function () {
 var self = this, args = arguments;
 var success = function() {
 return targetFunc.apply(self, args);
 };
 var error = function () {
 logger.log('applyBefore aspect failed to pass');
 //log the error and throw new error
 throw new Error('applyBefore aspect failed to pass');
 };
 var aspectResult = aspect.apply(null, Array.prototype.concat([error, success, self], args));
 return aspectResult;
 };
 }
};

Full implementation can be found at http://www.jeffjin.net/aop-with-javascript

answered Apr 21, 2013 at 4:20

1 Comment

This implementation is as far away from AOP as can be, because it does not provide any abstraction to both, neither Joinpoint nor Aspect. With a more close look it does not even qualify for a basic before method-modifier. Its first argument is expected to be a function, but again referred wrongly to as aspect, even though, in terms of AOP, it might relate closely to an advice handler.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.