public
Created

Waits for functions to complete before running complete

  • Download Gist
README.md
Markdown

Unfinished and not tested beyond my own case.

Usage

var wait = new Wait();
wait.complete(function () {
  console.log('we are done - now report');
});

$.get(url, wait.until(function (data) {
  // do something with data
});

db.users.find(wait.until(function (err, docs) {
  // we've found users in the mongo db
}));
wait.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
Wait = function (complete) {
if (complete) this.oncomplete = complete;
};
 
Wait.prototype = {
debug: false,
log: function () {
if (!this.debug) return;
var args = [].slice.apply(arguments);
if (typeof args[0] == 'string') args[0] = '[wait] ' + args[0];
else args.unshift('[wait]');
console.log.apply(console, args);
},
oncomplete: function () {},
complete: function (fn) {
if (fn === undefined) {
this.oncomplete();
} else {
this.oncomplete = fn;
}
},
tasks: 0,
done: function () {
this.tasks--;
this.log('tasks left: ' + this.tasks);
if (this.tasks == 0) {
this.log('triggering complete')
this.complete();
}
},
until: function (task, context) {
var self = this,
name = (arguments.callee.name || 'anonymous');
this.tasks++;
 
context || (context = this);
this.log('new task: %s, total: %d', (arguments.callee.name || 'anonymous'), this.tasks);
return function () {
self.log('running %s', name);
var ret,
args = [].slice.apply(arguments);
// args.push(self.done);
try {
ret = task.apply(context, args);
} catch (e) {
console.error(e);
}
self.done();
return ret;
};
},
run: function (task, context) {
return this.add(task, context)();
}
};
 
if (typeof module !== undefined && module.exports !== undefined) {
module.exports = Wait;
}
//using jQuery deferreds (assuming db.users.find returns compatible promise/deferred object )

var p1 = $.get(url, function(data){
   //do smth with data
});


var p2 = new jQuery.Deferred();
db.users.find(function(err, docs){
  p2.resolve(docs);
})

jQuery.when(p1, p2).then(function(data, docs){
  //maybe do something with data and docs
})

Also - I'm not using jQuery - because I'm in Node.js.

Maybe have a look at when.js's when.all and when.reduce. They can join multiple tasks, and might do what you need. Here's a quick take on the original wait usage with when.js:

var when, apply, p1, p2;

when = require('when');
apply = require('when/apply');

var p1, p2;

p1 = $.get(url);

p2 = when.defer();
db.users.find(function (err, docs) {
  // we've found users in the mongo db
  p2.resolve(docs);
});

when.all([p1, p2],
    function(results) {
        // results[0] is p1 result
        // results[1] is p2 result
        console.log('we are done - now report');
    }
);

// Or use when/apply to spread results onto function args
when.all([p1, p2],
    apply(function(data, docs) {
        console.log('we are done - now report');
    })
);

// Could also use when.reduce (promise-aware Array.proto.reduce)
// to reduce the results.
// Here's a simple string concat
when.reduce([p1, p2],
    function(finalResult, current) {
        return finalResult + current;
    }, '') // initial value is empty string
.then(
    function(finalResult) {
        console.log('we are done - now report');    
    }
);

Unlike jQuery's Deferred, when.js is compliant with the defacto standard (CommonJS Promises/A), runs in browsers and node (and probably RingoJS), and even converts non-compliant promises like $.Deferred to compliant ones. #WIN

FWIW, yep, when.js 1.0.2 (probably earlier versions, too) works in Ringo 0.8.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.