Skip to content

Instantly share code, notes, and snippets.

@AutoSponge
Created December 7, 2012 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AutoSponge/4236433 to your computer and use it in GitHub Desktop.
Save AutoSponge/4236433 to your computer and use it in GitHub Desktop.
AOP with callbacks
function createAspect(fn) {
var _1 = jQuery.Callbacks(),
_2 = jQuery.Callbacks(),
_3 = jQuery.Callbacks(),
args, result;
function aspect() {
args = arguments;
_2.fireWith(this, args);
return result;
}
aspect.before = function (fn) {
_1.add(fn);
return this;
};
aspect.after = function (fn) {
_3.add(fn);
return this;
};
_2.add(function () {
_1.fireWith(this, arguments);
}, function () {
result = fn.apply(this, arguments);
}, function () {
_3.fireWith(this, [result, arguments]);
});
return aspect;
}
var obj = {
add: function () {
this.num += Array.prototype.reduce.call(arguments, function (a, b) {
return a + b;
});
return this.num;
},
num: 1
};
obj.add = createAspect(obj.add);
obj.add.before(function () {
console.log("adding " + Array.apply(null, arguments) + " to num.");
this.start = this.num;
})
.after(function (result, args) {
console.log("num is now " + result);
this.end = this.num;
});
obj.add(1, 2, 3);
obj.add.call(obj, 4, 5, 6);
console.log(obj.num);
/* an implementation with promises */
function isPromise(obj) {
return obj && typeof obj === "object" && typeof obj.then === "function";
}
function makePromise(possiblePromise) {
var dfd, action;
var promise = possiblePromise;
if (!isPromise(promise)) {
dfd = new jQuery.Deferred();
action = typeof possiblePromise === "undefined" || possiblePromise ? "resolve" : "reject";
dfd[action](possiblePromise);
promise = dfd.promise();
}
return promise;
}
function flow(handlers, that, args) {
var when = [];
for (var i = 0, len = handlers.length; i < len; i += 1) {
when.push(makePromise(handlers[i].apply(that, args)));
}
return jQuery.when.apply(null, when);
}
function createDeferredAspect(fn) {
var before = [],
after = [];
function aspect() {
var that = this;
var dfd = jQuery.Deferred();
args = arguments;
flow(before, that, args)
.done(function () {
makePromise(fn.apply(that, args))
.done(function () {
return flow(after, that, args)
.done(function () {
dfd.resolve();
});
});
});
return dfd.promise();
}
aspect.before = function (fn) {
before.push(fn);
return this;
};
aspect.after = function (fn) {
after.push(fn);
return this;
};
return aspect;
}
var def = {
waitAdd: function () {
var d = jQuery.Deferred();
var args = arguments;
var self = this;
function add(a, b) {
return a + b;
}
setTimeout(function () {
self.num += Array.prototype.reduce.call(args, add);
console.log("added: " + self.num);
d.resolve();
}, 100);
return d.promise();
},
num: 1
};
def.waitAdd = createDeferredAspect(def.waitAdd);
def.waitAdd.before(function () {
console.log("before: " + this.num);
});
def.waitAdd.after(function () {
console.log("after: " + this.num);
});
def.waitAdd(1, 2, 3);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment