2009-06-17 6 views

Antwort

30

ist, was ich bis jetzt gefunden:

  • dotvoid ‚s Implementierung, sauberen Syntax, nett zu benutzen, wobei der Artikel eine gute Einführung ist, warum/wie den angegebenen Code zu verwenden, Einführungen unterstützt, aber abgehört wird, hat
  • Dojo, was scheint ein guter Einbau-Implementierung in dojox, here ist eine schöne Einführung werden, wie es zu benutzen,
  • es ein Plugin für jQuery ist, jquery-aop, mit einer raueren Syntax, vorbei Objekte und Methoden in einem JavaScript-Objekt,
  • AspectJS mit einer noch gröberen Syntax (müssen Art von pointcut als Argument an eine einzigen Methode zu übergeben)

Wie ich, Code des dotvoid funktioniert nicht gesagt. korrigierte ich ein wenig und bekam etwas, das besser zu funktionieren scheint:

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; 
     } 
} 
+0

Ist der Code irgendwie funktioniert in Internet Explorer zu finden? Als meine Tests fehlschlugen, googelte ich herum und es scheint, dass IE keine "Prototyp" -Eigenschaft hat ... –

+0

Ich habe Tests auf diesem IE7 ausgeführt. Funktioniert gut. Niedrigere Versionen jedoch nicht getestet. – glmxndr

+1

2014: Ich fand diesen immer noch sehr aktiven Rahmen [jsAspect] (https://github.com/antivanov/jsAspect) es scheint zu tun, was ein AOP tun sollte! –

13

Haben Sie meld.js und aop.js von https://github.com/cujojs gesehen?

SpringSource bietet AOP-Funktionalität, zusätzlich zu einer Reihe anderer nützlicher Dinge für fortgeschrittene Javascript-Programmierer.

Haftungsausschluss: Ich arbeite für SpringSource.

+0

Es ist eine ziemlich alte Frage ... aber danke für den Zusatz. – glmxndr

3

Basierend auf dotvoid-Lösung, habe ich meine eigene Version von JS AOP für meine eigenen Projekte erstellt. Ich möchte im Grunde die Aspekt Setup-Kosten minimieren, so fügte ich Aspekt Setup-Funktionalität unter Function.prototype.

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

Ich muss auch unterstützen, Synchronisierungsrückrufe, wie die Unterstützung der Authentifizierung und Autorisierung für bestimmte Methoden. Zum Beispiel:

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(); 

Um dies zu implementieren, ich brauche die Sicherheit und und weiterhin auf Erfolg oder stoppen Ausführung bei einem Fehler auszuführen.

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; 
     }; 
    } 
}; 

Die vollständige Umsetzung kann bei http://www.jeffjin.net/aop-with-javascript

Verwandte Themen