Git Product home page Git Product logo

angular-aop's Issues

joinpoint.proceed()

Hi,

This issue is for a feature

I would like to have a way to change the args in the join-point. Some AOP lib have something like:

joinpoint.proceed(newArg1, newArg2, ...)

where:

  • When, called, causes the original method to be invoked
  • When called without arguments, the original arguments will be passed.
  • When called with arguments, they will be passed
    instead of the original arguments

I currently am forced to modify the joinpoint.args which is not very clean and also does not allow aspects like memoize as the original method is always invoked.

Cheers,
Jose

Typescript: undefined is not a function

I've been trying to integrate aop for logging, and followed both the README and a post you've made, with no luck.

My typescript:

/// <reference path="/typings/angularjs/angular.d.ts" />

interface Window { TEST : any; }

module MyApp {
  "use strict";

  export function boot(
    $log : ng.ILogService
  ) {
    $log.info("starting");
  }

  angular
    .module("my_app", [
      "uuid4",
      "ngTouch",
      "AngularAOP"
    ])
    .factory("log_aspect", [() => {
      return (data : any) => {
        console.log("==== HELLO ====");
        console.log(data);
      };
    }])
    .factory("DummyService", [() => {
      return {
        foo: () => { console.log("---- foo ----"); },
        bar: (a : any, b : any) => {
          console.log("---- bar ----", a, b);
          return a * b;
        }
      };
    }])
    .controller("BusController", [
      "DummyService",
      (DummyService : any) => {
        DummyService.foo();
        DummyService.bar(2, 3.14);
      }
    ])
    .config( ($provide : any, executeProvider : any) => {
      executeProvider.annotate($provide, {
        DummyService: [{
          jointPoint: "after",
          advice: "log_aspect"
        }]
      });
    })
    .run([
      "$log",
      window.TEST ? () => {} : boot
    ]);
}

and compiled js:

var MyApp;
(function (MyApp) {
    "use strict";
    function boot($log) {
        $log.info("starting");
    }
    MyApp.boot = boot;
    angular.module("my_app", [
        "uuid4",
        "ngTouch",
        "AngularAOP"
    ]).factory("log_aspect", [function () {
        return function (data) {
            console.log("==== HELLO ====");
            console.log(data);
        };
    }]).factory("DummyService", [function () {
        return {
            foo: function () {
                console.log("---- foo ----");
            },
            bar: function (a, b) {
                console.log("---- bar ----", a, b);
                return a * b;
            }
        };
    }]).controller("BusController", [
        "DummyService",
        function (DummyService) {
            DummyService.foo();
            DummyService.bar(2, 3.14);
        }
    ]).config(function ($provide, executeProvider) {
        executeProvider.annotate($provide, {
            DummyService: [{
                jointPoint: "after",
                advice: "log_aspect"
            }]
        });
    }).run([
        "$log",
        window.TEST ? function () {
        } : boot
    ]);
})(MyApp || (MyApp = {}));

with console output:

 TypeError: undefined is not a function
    at Object.AspectBuilder._getFunctionAspect (main.js:11417)
    at Object.AspectBuilder._getObjectAspect (main.js:11434)
    at AspectCollection.AspectBuilder.buildAspect [as after] (main.js:11412)
    at main.js:11392
    at Object.invoke (main.js:3944)
    at Object.origProvider.$get (main.js:3896)
    at Object.invoke (main.js:3944)
    at main.js:3974
    at getService (main.js:3930)
    at Object.invoke (main.js:3942)

If there's any help you can provide it would be greatly appreciated! Really want to integrate this~


2015-02-14: Edited to port full typescript and compiled js

Enhancement: add pointcut onNotify

I wish to use AngularAOP in a project I'm working on, the use case I'm thinking of would really benefit from being able to define pointcuts for the notify callback. Are there any plans of introducing this? If you are not able to work on it yourself: would you accept a pull request?

ngResource gets incorrectly wrapped into a function aspect

I'm using angular-aop to put an around advice for the ngResource I use to call server-side API. Like this:

myServices.factory('WelcomeService', [ '$resource', 'execute', 'MyAroundAspect', 
      function($resource, execute, ServerCommState ) {
          return execute(MyAroundAspect).around( $resource('/api/welcome/:id', {
              id: '@id'
          }, {
              create: {
                  method: 'POST',
                  params: {
                      nick: '@nick'
                  }   
              },  
              update: {
                  method: 'PUT'
              }
          }));
      }
  ]);

When calling this service's get method, I get an undefined exception, unless I modify angular-aop.js like this:

  //Builds specified aspect
  AspectBuilder = { 
      buildAspect: function (advice, pointcut) {
        var self = this;
        return function (target, rules) {
          // if (typeof target === 'function') {
          //   return self._getFunctionAspect(target, pointcut, advice);
          // } else if (target) {
            return self._getObjectAspect(target, rules || {}, pointcut, advice);
          // }
        };  
      },  

As you may see, I modify the code so buildAspect always return an object aspect. With this modification, the MyAroundAspect gets called, twice per service call.

My solution is not an ideal one, but I'm not using function aspects, so that's fine for me. However, what should be done in order to enable AOP for ngResource without disabling function advices ?

resolveArgs is empty in onResolve and AfterResolve

First of all thanks for this awesome package.

My issue is that I noticed that the resolveArgs parameter seems to be always an empty object. I replicated this with the example ArticlesCollection service.

Service:

angular.module('core').factory('ArticlesCollection', function ($q, $timeout) {
  var sampleArticles = [
      { id: 0, title: 'Title 1', content: 'Content 1' },
      { id: 1, title: 'Title 2', content: 'Content 2' },
      { id: 2, title: 'Title 3', content: 'Content 3' }
    ],
    privateArticles = [
      { id: 3, title: 'Title 4', content: 'Content 4' },
      { id: 4, title: 'Title 5', content: 'Content 5' }
    ],
    api = {
      loadArticles: function () {
        var deferred = $q.defer();
        $timeout(function () {
          deferred.resolve(sampleArticles);
        }, 1000);
        return deferred.promise;
      },
      getArticleById: function (id) {
        for (var i = 0; i < sampleArticles.length; i += 1) {
          if (sampleArticles[i].id === id)  {
            return sampleArticles[i];
          }
        }
        return undefined;
      },
      getPrivateArticles: function () {
        return privateArticles;
      }
    };
  return api;
});

Logger:

angular.module('core').factory('Logger', function () {
    return function (args) {
      console.log(angular.toJson(args));
    };
});

Angular-aop config:

angular.module('core').config(function ($provide, executeProvider) {
    executeProvider.annotate($provide, {
        ArticlesCollection: [
            {
                jointPoint: executeProvider.ON_RESOLVE,
                advice: 'Logger'
            },
            {
                jointPoint: executeProvider.AFTER_RESOLVE,
                advice: 'Logger'
            }
          ]
    });
});

Karma test:

(function () {
    ddescribe('ArticlesCollection Service Tests', function () {
        var service;
        // Then we can start by loading the main application module
        beforeEach(module(ApplicationConfiguration.applicationModuleName));

        // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
        // This allows us to inject a service but then attach it to a variable
        // with the same name as the service.
        beforeEach(inject(function ($templateCache, $rootScope, _ArticlesCollection_, $timeout) {
            service = _ArticlesCollection_;
        }));

        it('loadArticles should return articles', inject(function ($timeout) {
          service.loadArticles().then(function(articles) {
            console.log('articles:' + articles);
            expect(articles.length).toEqual(3);
          });
          $timeout.flush();
        }));
    });
}());

Test Results:

Running "karma:unit" (karma) task
INFO [karma]: Karma v0.12.37 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Windows 8 0.0.0)]: Connected on socket vJLU_9iOvsW-83cbU21Z with id 41041485
LOG: '{"when":"onResolve","method":"loadArticles","args":[],"resolveArgs":{}}'
LOG: 'articles:[object Object],[object Object],[object Object]'
LOG: '{"when":"afterResolve","method":"loadArticles","args":[],"resolveArgs":{}}'
PhantomJS 1.9.8 (Windows 8 0.0.0): Executed 1 of 228 SUCCESS (0.121 secs / 0.038 secs)

To me the resolveArgs attribute sounds like it should contain the argument the deferred.resolve() returns, in this case the sampleArticles array. Please correct me if my understanding is wrong. Thanks.

IE9

Hello,

This lib seems not to work with IE9. Is IE9 supported?

Reduce the number of recursively wrapped aspects

Minko,

One BIG downside of AOP is it makes it harder to debug methods that have aspects applied. One pain point is that when inspecting objects in say chrome developer tools you no longer can hover over a method on an object and see a preview of the method.

Now you have to drill down through multiple levels of wrappers to see this preview as per the attached screen shot
image

One way to reduce this pain is to reduce this nesting. Instead of creating a wrapper for each aspect that is applied to a method, I think a better alternative would be to maintain a single wrapper that collects all the aspects that have been applied to the method. This single wrapper would maintain a stack for each pointcut.

When inspecting an object in the locals window of chrome you would be able to expand each stack to see the list of aspects applied.

Without the above, I think code decorated using the angular-aop library will be too much of a pain to work with once aspects start to pile up on top of one another.

What do you think?

Christian

Name of the original function cannot be determined when function called without a context

It's possible that a public method of an angular service will be called as a "standalone" function without a function receiver being defined - eg: someFunction.call(null)

When this happens and the original method was created as an anonymous function then the name of the function cannot be determined.

I have a solution to this: remember the name of the service property to which the function was originally bound. I'm going to send a pull request for this...

AngularAOP for advising controller

Hi there,
Currently, I see that AngularAOP on has the support for advising Angular's service. However, it might be useful if it can support advising controllers as well, because you can have Authorization, Exception handling in controllers, not only in services.

Would be very nice to have that,
Cheers

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.