Create a gist now

Instantly share code, notes, and snippets.

Embed
Waits for functions to complete before running complete

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 = 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;
}
@karlbohlmark

This comment has been minimized.

Show comment
Hide comment
@karlbohlmark

karlbohlmark Feb 18, 2012

//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
})
//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
})
@remy

This comment has been minimized.

Show comment
Hide comment
@remy

remy Feb 18, 2012

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

Owner

remy commented Feb 18, 2012

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

@briancavalier

This comment has been minimized.

Show comment
Hide comment
@briancavalier

briancavalier Feb 18, 2012

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');    
    }
);

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');    
    }
);
@unscriptable

This comment has been minimized.

Show comment
Hide comment
@unscriptable

unscriptable Feb 18, 2012

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

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

@briancavalier

This comment has been minimized.

Show comment
Hide comment
@briancavalier

briancavalier Feb 20, 2012

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment