Closed 0xgeert closed 11 years ago
Hey @gbrits,
It sounds like you're looking for "around" advice. You have a reference to the joinpoint so you can decide to run the original function or not. Around advice is a bit more work to use, but is fairly straightforward.
https://github.com/cujojs/meld/blob/master/docs/api.md#meldaround
-- John
Great, I'll have a look thanks.
2013/3/2 John Hann notifications@github.com
Hey @gbrits https://github.com/gbrits,
It sounds like you're looking for "around" advice. You have a reference to the joinpoint so you can decide to run the original function or not. Around advice is a bit more work to use, but is fairly straightforward.
https://github.com/cujojs/meld/blob/master/docs/api.md#meldaround
-- John
— Reply to this email directly or view it on GitHubhttps://github.com/cujojs/meld/issues/14#issuecomment-14329157 .
Hey Brian, it's not clear to me how to ensure the after advice will be skipped. Does the advice have to throw? -- John
Hey @gbrits, yeah, the only advice type that is allowed to cancel a method invocation safely is around
. It's the most powerful. However, it cannot prevent other advices, such as after
from executing. This is pretty standard behavior for AOP implementations.
While you could use before
advice and throw an exception, the exception will propagate, which is probably not what you want.
One approach that may work for skipping certain advices may be to use a shared flag. An early advice type, such as before or around could set the flag when necessary, and later advices could simply look at the flag and do nothing if it is set. It's not a great solution--this is definitely a tricky use case!
Just so I understand fully: not calling joinpoint.proceed() in my around() would skip the original method invocation, but it wouldn' t stop other advices from running, correct?
Yep, that's correct (although there is a bit more to it, see below). Here is a simple example that only logs "after", even tho the around advice never calls joinpoint.proceed
:
var meld = require('meld');
var o = {
f: function() { console.log('o.f'); }
}
meld.add(o, 'f', {
around: function() {},
after: function() { console.log('after'); }
});
o.f();
You can think of around advice like "layers" or wrappers around the original method. As you apply more around advices, it adds more layers. So technically speaking, joinpoint.proceed
proceeds to the next "layer" of around advice, or, if there are no layers remaining, to the original method. For example:
var o = {
f: function() {
console.log('o.f');
}
}
meld.around(o, 'f', function(joinpoint) {
console.log('inner around');
});
meld.around(o, 'f', function(joinpoint) {
console.log('outer around');
return joinpoint.proceed();
});
This example will log "outer around" then "inner around", but will never log "o.f". The outer around calls jointpoint.proceed()
, which proceeds to the next layer, in this case, the inner around, which simply logs without calling joinpoint.proceed
, so the original method is never called.
Hope that helps!
Thanks that clarifies things! Cheers
2013/3/3 Brian Cavalier notifications@github.com
Yep, that's correct (although there is a bit more to it, see below). Here is a simple example that only logs "after", even tho the around advice never calls joinpoint.proceed:
var meld = require('meld');var o = { f: function() { console.log('o.f'); }} meld.add(o, 'f', { around: function() {}, after: function() { console.log('after'); }}); o.f();
You can think of around advice like "layers" or wrappers around the original method. As you apply more around advices, it adds more layers. So technically speaking, joinpoint.proceed proceeds to the next "layer" of around advice, or, if there are no layers remaining, to the original method. For example:
var o = { f: function() { console.log('o.f'); }} meld.around(o, 'f', function(joinpoint) { console.log('inner around');}); meld.around(o, 'f', function(joinpoint) { console.log('outer around'); return joinpoint.proceed();});
This example will log "outer around" then "inner around", but will never log "o.f". The outer around calls jointpoint.proceed(), which proceeds to the next layer, in this case, the inner around, which simply logs without calling joinpoint.proceed, so the original method is never called.
Hope that helps!
— Reply to this email directly or view it on GitHubhttps://github.com/cujojs/meld/issues/14#issuecomment-14352339 .
Great, glad to help. Is there something else we need to do with this issue? If not, please close it. If there is, though, please let us know and we can discuss further. Thanks!
I'd like to have before-aspect that does some validation and just entirely skips the execution of the method it was applied to (as well as the entire optional before, after-chain succeeding it) .
Is this possible?