Skip to content

Instantly share code, notes, and snippets.

@bguiz
Created October 20, 2013 11:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bguiz/7068093 to your computer and use it in GitHub Desktop.
Save bguiz/7068093 to your computer and use it in GitHub Desktop.
A comparison of async to qryq in specifying a compound query that is diamond-shaped. http://bguiz.com/post/64567226287/a-sneak-peek-from-my-talk-about-qryq-at-osdc-2013
var async = require('async');
var _ = require('underscore');
var api = {
add: function(qry, callback) {
if (!qry || ! _.isNumber(qry.a) || ! _.isNumber(qry.b)) {
callback('Must specify two numeric params, a and b. Params were: '+JSON.stringify(qry), null);
}
else {
callback(null, qry.a + qry.b);
}
},
multiply: function(qry, callback) {
if (!qry || ! _.isNumber(qry.a) || ! _.isNumber(qry.b)) {
callback('Must specify two numeric params, a and b. Params were: '+JSON.stringify(qry), null);
}
else {
callback(null, qry.a * qry.b);
}
}
};
async.waterfall([
function(callback) {
callback(null, {a: 3, b: 4});
},
api.add,
function(result1, callback) {
async.parallel([
function(cb) {
api.multiply({a: result1, b: 3}, cb);
},
function(cb) {
api.multiply({a: 7, b: result1}, cb);
}
],
function(err, parallelResult) {
callback(null, {a: parallelResult[0], b: parallelResult[1]});
});
},
api.add
],
function(err, diamondResult) {
console.log('diamondResult:', diamondResult);
});
/*
Notes:
- with async there is a need to use wrapper function whener parsing is necessary
- also to pass in the initial value
- with async, the syntax is a lot more verbose
- still need to think of how to "wire up" the function together by knowing their implementation
- not fully declarative
*/
var qryq = require('./qryq');
var _ = require('underscore');
var Q = require('q');
var api = {
add: function(deferred, qry) {
if (!qry || ! _.isNumber(qry.a) || ! _.isNumber(qry.b)) {
deferred.reject('Must specify two numeric params, a and b. Params were: '+JSON.stringify(qry));
}
else {
deferred.resolve(qry.a + qry.b);
}
},
multiply: function(deferred, qry) {
if (!qry || ! _.isNumber(qry.a) || ! _.isNumber(qry.b)) {
deferred.reject('Must specify two numeric params, a and b. Params were: '+JSON.stringify(qry));
}
else {
deferred.resolve(qry.a * qry.b);
}
}
};
var queryQueue = [
{id: "A", api: "add", qry:{a:3, b:4}},
{id: "B", api: "multiply", qry:{a:"#{A}", b:3}},
{id: "C", api: "multiply", qry:{a:7, b: "#{A}"}},
{id: "D", api: "add", qry:{a:"#{C}", b:"#{B}"}}
];
var deferred = Q.defer();
qryq.dependent(deferred, queryQueue, api);
deferred.promise.then(function(diamondResult) {
console.log('diamondResult:', JSON.stringify(diamondResult));
var qryDsResult = _.findWhere(diamondResult, {id: 'D'});
console.log('qryDsResult:', qryDsResult && qryDsResult.response && qryDsResult.response.value);
});
/*
- no need to think about how to wire up functions together
- fully declarative
- infers order of execution
- infers which query depends upon the other
- return value differs in philosophy
- rather than return only the final result (like async#waterfall), returns all of them (like async#parallel)
- execution does not stop when an error is encountered at some point in the chain
- errors are verbose, and inline with each query
- heaps easier to find out where a compound query has gone wrong
- requires an additional dependency: Q for promises
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment