Skip to content

Commit

Permalink
async used in Base.run.
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenplusplus committed May 22, 2013
1 parent 5d414ae commit f8f3fde
Showing 1 changed file with 36 additions and 61 deletions.
97 changes: 36 additions & 61 deletions lib/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var util = require('util');
var path = require('path');
var events = require('events');
var _ = require('lodash');
var async = require('async');

var engines = require('./util/engines');
var conflicter = require('./util/conflicter');
Expand Down Expand Up @@ -216,86 +217,60 @@ Base.prototype.argument = function argument(name, config) {
//
// Returns the generator instance.
Base.prototype.run = function run(args, cb) {
var self = this;
this._running = true;
this.emit('start');
this.emit('run');

if (!cb) {
cb = args;
args = this.args;
}

cb = cb || function () {};

var self = this;
this._running = true;
this.emit('start');
this.emit('run');
var runHooks = function () {
self.runHooks(cb);
};

var methods = Object.keys(Object.getPrototypeOf(this));
// As the end of the methods list processing has a signification and trigger a dedicated
// process (runHooks), and as Array.shift will always return undefined whatever the number
// of time we call it, we need to have a marker for the end of the list (this will help
// us to perform test in a synchronous way -- i.e. without prompting user)
methods.push(-1);

var waiter = 0;
(function next(method) {
if (!method) {
return;
}

if (method === -1) {
return self.runHooks(cb);
}
var resolve = function (method) {
var rules = {
underscore: method.charAt(0) !== '_',
initialize: !/^(constructor|initialize)$/.test(method),
isValid: function () {
return this.underscore && this.initialize;
}
};

if (method.charAt(0) === '_') {
return next(methods.shift());
}
return function (next) {
if (!rules.isValid(method)) {
return next();
}

if (/^(constructor|initialize)$/.test(method)) {
return next(methods.shift());
}
self.async = function () {
self.async.running = true;
return next;
};

// very very basic async management, could be done better using event and
// EventEmitter ability of Generators.
self.emit(method);
self.emit('method', method);
self[method].apply(self, args);

self.async = function async() {
waiter++;
return function (err) {
waiter--;
conflicter.resolve(function (err) {
if (err) {
self.emit('error', err);
}

if (waiter) {
return;
return self.emit('error', err);
}
});

conflicter.resolve(function (err) {
if (err) {
return self.emit('error', err);
}

next(methods.shift());
});
};
};

self.emit(method);
self.emit('method', method);

self[method].apply(self, args);

// async was called, assume asynchronous behaviour, and wait for completion
if (waiter) {
return;
}

conflicter.resolve(function (err) {
if (err) {
return self.emit('error', err);
if (!self.async.running) {
next();
}
next(methods.shift());
});
};
};

}(methods.shift()));
async.series(methods.map(resolve), runHooks);

return this;
};
Expand Down

0 comments on commit f8f3fde

Please sign in to comment.