Skip to content

Instantly share code, notes, and snippets.

@sillero
Last active January 1, 2016 05:19
Show Gist options
  • Save sillero/8097552 to your computer and use it in GitHub Desktop.
Save sillero/8097552 to your computer and use it in GitHub Desktop.
node-tasker

#node-tasker An exercise on Promises and flows (simulating Grunt tasks on a node server)

##Usage

tasker.registerTask('test1', function(){
    console.log('test1');
});

tasker.registerTask('test2', function(resolve, reject){
    console.log('test2');
});

tasker.registerTask('test3', ['test2', 'test1', 'test4', 'test5', 'abort1', 'test2']);

tasker.registerTask('abort1', 'A task to stop the flow', function(){
    console.log('Flow stopped');
    return false; //return false === stop the flow
});

tasker.registerTask('test5', ['test2', 'test1']);

tasker.registerTask('test4', 'This is task 4', function(){
    console.log('test4');
});

tasker.runTask('test3');
/* Console output
test2
test1
test4
test2
test1
Flow stopped
"abort1" task aborted
*/

##To do

  • Async tasks
  • Forced tasks
  • Nonlinear flow (Promise.all instead of Promise.then)
  • Dependency Injection
/*
dependency injection
http://stackoverflow.com/questions/20058391/javascript-dependency-injection
var Injector = {
   dependencies: {},
   add : function(qualifier, obj){
      this.dependencies[qualifier] = obj; 
   },
   get : function(func){
      var obj = new func;
      var dependencies = this.resolveDependencies(func);
      func.apply(obj, dependencies);
      return obj;
   },
   resolveDependencies : function(func) {
      var args = this.getArguments(func);
      var dependencies = [];
      for ( var i = 0; i < args.length; i++) {
         dependencies.push(this.dependencies[args[i]]);
      }
      return dependencies;
   },
   getArguments : function(func) {
      //This regex is from require.js
      var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
      var args = func.toString().match(FN_ARGS)[1].split(',');
      return args;
   }
};
 */
{
"name": "tasker",
"version": "0.0.2",
"description": "Tasks on NodeJS, Grunt style /o/",
"main": "tasker.js",
"dependencies": {
"underscore": "~1.5.2",
"promise": "~3.2.0",
"grunt": "~0.4.2"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Gustavo Sillero - @sillero",
"license": "BSD-2-Clause"
}
var _ = require('underscore'),
Promise = require('promise'),
_gFile = require('grunt/lib/grunt/file'),
Tasker = function(){
var tasker = this;
tasker.file = _gFile;
tasker.log = function(){
this.ok = function(){
var args = Array.prototype.slice.call(arguments);
console.log.apply(this, ['OK>>> '].concat(args));
};
var args = Array.prototype.slice.call(arguments);
console.log.apply(this, args);
};
tasker.tasks = {};
tasker.task = {};
/**
* Register a new task or override one
*
* tasker.registerTask(name, tasks)
* @param {String} name
* @param {Array} tasks
*
* tasker.registerTask(name, action)
* @param {String} name
* @param {Function} action
*
* tasker.registerTask(name, description, action)
* @param {String} name
* @param {String} description
* @param {Function} action
*
* @return {Promise}
*/
tasker.task.register = function(){
var args = Array.prototype.slice.call(arguments),
task = {
name: args[0],
description: '',
tasks: [],
action: function(){}
};
return Promise(function(resolve, reject){
if (args.length === 2) {
if (_.isFunction(args[1])) {
task.action = args[1];
}
else if (_.isArray(args[1])) {
task.tasks = args[1];
}
}
else if (args.length === 3) {
task.description = args[1];
task.action = args[2];
}
tasker.tasks[task.name] = task;
resolve();
});
};
/**
* Run a task
* @param {String} taskName
* @return {Promise}
*/
tasker.task.run = function(taskName){
var allTasks = this.tasks,
thisTask = this.tasks[taskName],
chainTasks = function chain(thisTask){
var tasksQueue = [];
if (thisTask.tasks.length) {
thisTask.tasks.forEach(function(item){
tasksQueue = tasksQueue.concat(chain(allTasks[item]));
});
}
else {
tasksQueue.push(thisTask);
}
return tasksQueue;
},
promises = function(taskArray){
var getPromise = function(task){
return Promise(function(resolve, reject){
var keepGoing = true,
error = false;
try {
keepGoing = task.action();
}
catch (e) {
error = e;
}
if (keepGoing === false || error) {
reject();
if (error) {
console.log(error);
}
else {
console.log('"'+ task.name + '" task aborted');
}
}
else {
resolve();
}
});
},
p = getPromise(taskArray.shift());
taskArray.forEach(function(task){
p = p.then(function(){
return getPromise(task);
});
});
return p;
};
return promises(chainTasks(thisTask));
};
tasker.registerTask = tasker.task.register;
tasker.runTask = tasker.task.run;
};
module.exports = new Tasker();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment