123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- 'use strict';
- function Kareem() {
- this._pres = {};
- this._posts = {};
- }
- Kareem.prototype.execPre = function(name, context, callback) {
- var pres = this._pres[name] || [];
- var numPres = pres.length;
- var numAsyncPres = pres.numAsync || 0;
- var currentPre = 0;
- var asyncPresLeft = numAsyncPres;
- var done = false;
- if (!numPres) {
- return process.nextTick(function() {
- callback(null);
- });
- }
- var next = function() {
- if (currentPre >= numPres) {
- return;
- }
- var pre = pres[currentPre];
- if (pre.isAsync) {
- pre.fn.call(
- context,
- function(error) {
- if (error) {
- if (done) {
- return;
- }
- done = true;
- return callback(error);
- }
- ++currentPre;
- next.apply(context, arguments);
- },
- function(error) {
- if (error) {
- if (done) {
- return;
- }
- done = true;
- return callback(error);
- }
- if (--numAsyncPres === 0) {
- return callback(null);
- }
- });
- } else if (pre.fn.length > 0) {
- var args = [function(error) {
- if (error) {
- if (done) {
- return;
- }
- done = true;
- return callback(error);
- }
- if (++currentPre >= numPres) {
- if (asyncPresLeft > 0) {
- // Leave parallel hooks to run
- return;
- } else {
- return callback(null);
- }
- }
- next.apply(context, arguments);
- }];
- if (arguments.length >= 2) {
- for (var i = 1; i < arguments.length; ++i) {
- args.push(arguments[i]);
- }
- }
- pre.fn.apply(context, args);
- } else {
- pre.fn.call(context);
- if (++currentPre >= numPres) {
- if (asyncPresLeft > 0) {
- // Leave parallel hooks to run
- return;
- } else {
- return process.nextTick(function() {
- callback(null);
- });
- }
- }
- next();
- }
- };
- next();
- };
- Kareem.prototype.execPost = function(name, context, args, callback) {
- var posts = this._posts[name] || [];
- var numPosts = posts.length;
- var currentPost = 0;
- if (!numPosts) {
- return process.nextTick(function() {
- callback.apply(null, [null].concat(args));
- });
- }
- var next = function() {
- var post = posts[currentPost];
- if (post.length > args.length) {
- post.apply(context, args.concat(function(error) {
- if (error) {
- return callback(error);
- }
- if (++currentPost >= numPosts) {
- return callback.apply(null, [null].concat(args));
- }
- next();
- }));
- } else {
- post.apply(context, args);
- if (++currentPost >= numPosts) {
- return callback.apply(null, [null].concat(args));
- }
- next();
- }
- };
- next();
- };
- Kareem.prototype.wrap = function(name, fn, context, args, useLegacyPost) {
- var lastArg = (args.length > 0 ? args[args.length - 1] : null);
- var _this = this;
- this.execPre(name, context, function(error) {
- if (error) {
- if (typeof lastArg === 'function') {
- return lastArg(error);
- }
- return;
- }
- var end = (typeof lastArg === 'function' ? args.length - 1 : args.length);
- fn.apply(context, args.slice(0, end).concat(function() {
- if (arguments[0]) {
- // Assume error
- return typeof lastArg === 'function' ?
- lastArg(arguments[0]) :
- undefined;
- }
- if (useLegacyPost && typeof lastArg === 'function') {
- lastArg.apply(context, arguments);
- }
- var argsWithoutError = Array.prototype.slice.call(arguments, 1);
- _this.execPost(name, context, argsWithoutError, function() {
- if (arguments[0]) {
- return typeof lastArg === 'function' ?
- lastArg(arguments[0]) :
- undefined;
- }
- return typeof lastArg === 'function' && !useLegacyPost ?
- lastArg.apply(context, arguments) :
- undefined;
- });
- }));
- });
- };
- Kareem.prototype.createWrapper = function(name, fn, context) {
- var _this = this;
- return function() {
- var args = Array.prototype.slice.call(arguments);
- _this.wrap(name, fn, context, args);
- };
- };
- Kareem.prototype.pre = function(name, isAsync, fn, error) {
- if (typeof arguments[1] !== 'boolean') {
- error = fn;
- fn = isAsync;
- isAsync = false;
- }
- this._pres[name] = this._pres[name] || [];
- var pres = this._pres[name];
- if (isAsync) {
- pres.numAsync = pres.numAsync || 0;
- ++pres.numAsync;
- }
- pres.push({ fn: fn, isAsync: isAsync });
- return this;
- };
- Kareem.prototype.post = function(name, fn) {
- (this._posts[name] = this._posts[name] || []).push(fn);
- return this;
- };
- Kareem.prototype.clone = function() {
- var n = new Kareem();
- for (var key in this._pres) {
- n._pres[key] = this._pres[key].slice();
- }
- for (var key in this._posts) {
- n._posts[key] = this._posts[key].slice();
- }
- return n;
- };
- module.exports = Kareem;
|