29

Вопрос по javascript – Библиотеки AOP Javascript [закрыто]

Какую библиотеку Javascript AOP вы используете и каковы ее основные функции?

  • Работает ли код как-то в Internet Explorer? Так как мои тесты не прошли, я погуглил, и, похоже, в IE нет "prototype" -property ...

    от
  • Я проводил тесты по этому вопросу в IE7. Работает отлично. Более низкие версии не проверены, хотя.

    от glmxndr
  • 2014: я нашел эту все еще очень активную структуруjsAspect кажется, что делает то, что должен делать АОП!

    от
  • Это довольно старый вопрос ... но спасибо за добавление.

    от glmxndr
  • 13

    Ты видел от

    Ты виделmeld.js а такжеaop.js от https://github.com/cujojs?

    SpringSource предоставляет функциональность AOP там, в дополнение к куче других полезных вещей для продвинутых программистов Javascript.

    Disclaimer: Я работаю на SpringSource.

  • 3

    Основываясь на решении dotvoid

    я создал свою собственную версию JS AOP для нужд своих проектов. Я в основном хочу минимизировать затраты на настройку аспекта, поэтому я добавил функциональность настройки аспекта в Function.prototype.

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

    Мне также нужно поддерживать обратные вызовы aync, такие как поддержка аутентификации и авторизации для определенных методов. Например:

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

    Чтобы реализовать это, мне нужно запустить защиту и продолжить работу в случае успеха или остановить выполнение в случае ошибки.

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

    Полная реализация может быть найдена вhttp://www.jeffjin.net/aop-with-javascript

  • 30

    Вот что я нашел до сих пор:

    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)

    Как я уже сказал, код dotvoid не работает. Я немного исправил и получил что-то, что, кажется, работает лучше:

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