Pergunta

biblioteca que Javascript AOP você usa, e quais são suas principais características?

Foi útil?

Solução

Aqui está o que eu encontrei até agora:

  • dotvoid de implementação, a sintaxe limpa , bom para uso, o artigo é uma introdução boa sobre o porquê / como usar o código fornecido, suporta apresentações, mas está grampeada,
  • Dojo tem o que parece ser um bom built-in aplicação em dojox , aqui é uma introdução agradável sobre como para usá-lo,
  • existe um plugin para jQuery, jquery-aop , com uma sintaxe mais áspero , passando objetos e métodos em um objeto javascript,
  • AspectJS com uma sintaxe ainda pior (necessidade de passar tipo de pointcut como argumentos para um único método)

Como eu disse, o código do dotvoid não funcionou. Eu corrigi um pouco e tem algo que parece funcionar melhor:

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

Outras dicas

Você viu meld.js e aop.js de https://github.com/cujojs ?

SpringSource fornece funcionalidade AOP lá, além de um monte de outras coisas úteis para programadores avançados de Javascript.

Aviso :. Eu trabalho para SpringSource

Com base na solução dotvoid, eu criei minha própria versão de JS AOP para meus próprios projetos necessidades. Basicamente, eu quero minimizar os custos de instalação aspecto, então eu adicionei funcionalidade de configuração aspecto em Function.prototype.

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

Eu também preciso apoiar aync retornos de chamada, como o apoio de autenticação e autorização para certos métodos. Por exemplo:

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

Para implementar isso, eu preciso executar a segurança e e continuar no sucesso ou execução de parada em caso de falha.

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

A implementação completa pode ser encontrada no http://www.jeffjin.net/aop-with- javascript

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top