// Your typical synchronous code
var getQueryResult = function (query) {
var result = execQuery(userId);
return result;
}
var result = getQueryResult('SELECT ?s WHERE { ?s ?p ?o }');
contaner.render(result);
// Both execQuery & getQueryResult are async
var getQueryResult = function (query, cb) {
execQuery(query, function(res) {
res = res.toArray();
cb(res);
});
}
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }', function(res) {
container.render(res);
});
var getQueryResult = function (query, cb) {
execQuery(query, function(res) {
expandResults(res, function(expandedRes) {
filterResults(res, function(finalRes){
finalRes = finalRes.toArray();
cb(finalRes);
});
});
});
}
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }', function(res) {
container.render(res);
});
The Pyramid of Doom
var processFinal = function (cb, finalRes){
cb(res);
}
var processExpandedResult = function (cb, expandedRes) {
filterResults(res, processFinal.bind(this, cb));
}
var processQueryResult = function (cb, res) {
expandResults(res, processExpandedResult.bind(this, cb));
}
var getQueryResult = function (query, cb) {
execQuery(query, processQueryResult.bind(this, cb));
}
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }', function(res) {
container.render(res);
});
Still messy
var getQueryResult = function (query) {
var result = execQuery(userId);
return result;
}
var result = getQueryResult('SELECT ?s WHERE { ?s ?p ?o }');
if(result.error) {
return container.error(result.error);
}
container.render(result.data);
// Both execQuery & getQueryResult are async
var getQueryResult = function (query, cb) {
execQuery(query, function(err, res) {
if(err) {
return cb(err);
}
res = res.toArray();
cb(null, res);
});
};
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }', function(err, res){
if(err) {
return container.error(err);
}
container.render(res);
});
Easy to learn but do not scale very well (get complex very quick)
.then
method.then
takes two functions as arguments: onFulfilled, onRejected.then
must return a promiseSee full spec for Promises/A+ on github.
var queryPromise = getQueryResult('SELECT ?s WHERE { ?s ?p ?o }');
// Some time later
promisedPic.then(function(res) {
container.render(res);
});
It doesn't matter if it has been fulfilled yet or not
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }')
.then(function(res) {
return filterResults(res)
.then(function(filteredRes) {
container.render(filteredRes);
});
});
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }')
.then(function(res) {
return filterResults(res);
})
.then(function(res) {
container.render(res);
});
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }')
.then(function(res) {
return filterResults(res);
})
.then(function(res) {
container.render(res);
},
function(err) {
contaner.error(err);
});
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }')
.then(function(res) {
return filterResults(res);
})
.then(function(res) {
container.render(res);
})
.catch(function(err) {
container.error(err);
});
Fully featured promise library with focus on innovative features and performance
.bind()
method that allow currying promises
var readFile = Promise.promisify(require("fs").readFile);
readFile("myfile.js", "utf8")
.then(function(contents){
return eval(contents);
}).then(function(result){
console.log("The result of evaluating myfile.js", result);
}).catch(function(e){
console.log("Error reading file", e);
});
var fs = Promise.promisifyAll(require("fs"));
fs
.readFileAsync("myfile.js", "utf8")
.then(function(contents){
console.log(contents);
}).catch(function(e){
console.error(e.stack);
});
function getDataFor(input, callback) {
return dataFromDataBase(input).nodeify(callback);
}
task.js (Mozilla)
spawn(function*() {
var data = yield $.ajax(url);
$('#result').html(data);
var status = $('#status').html('Download complete.');
yield status.fadeIn().promise();
yield sleep(2000);
status.fadeOut();
});
function delay(ms) {
return new Promise(function(f){ setTimeout(f, ms); });
}
function PingPong() {}
PingPong.prototype.ping = Promise.coroutine(function* (val) {
console.log("Ping?", val)
yield delay(500)
this.pong(val+1)
});
PingPong.prototype.pong = Promise.coroutine(function* (val) {
console.log("Pong!", val)
yield delay(500);
this.ping(val+1)
});
var a = new PingPong();
a.ping(0);
Built using node-fibers and Promises.
var getQueryResult = function (query, cb) {
execQuery(query, function(res) {
expandResults(res, function(expandedRes) {
filterResults(res, function(finalRes){
cb(res);
});
});
});
}
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }', function(res) {
container.render(res);
});
var getQueryResult = async(function(query) {
var res = await(execQuery(query));
var expandedRes = await(expandResults(res));
var finalRes = await(filterResults(res));
return finalRes;
});
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }').then(function(res) {
container.render(res);
});
var getQueryResult = function (query) {
var res = execQuery(query);
finalRes = processResults(res);
container.render(finalRes);
}
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }');
var getQueryResult = compose([
execQuery,
processResults,
container.render.bind(container)
]);
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }');
var getQueryResult = function (query, cb) {
container.showProgressIndicator();
execQuery(query, function(res) {
processResults(res, function(finalRes) {
container.render(finalRes);
cb();
});
});
}
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }', function() {
container.hideProgressIndicator();
});
var getQueryResult = composeAsync([
perform(container.showProgressIndicator.bind(container)),
execQuery,
processResults,
perform(container.render.bind(container))
]);
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }',
container.hideProgressIndicator.bind(container));
var getQueryResult = compose([
execQuery,
processResults,
container.render.bind(container)
]);
Same structure as sync
No need to change paradigm
// If you like jQuery or promises chains
var getQueryResult =
perform(container.showProgressIndicator.bind(container))
.map(execQuery)
.map(processResults)
.perform(container.render.bind(container));
getQueryResult
.perform(container.hideProgressIndicator.bind(container))
('SELECT ?s WHERE { ?s ?p ?o }');
// Reversed order
var getQueryResult = async.compose(
execQuery,
processResults,
// perform not in Async
perform(container.showProgressIndicator.bind(container))
);
getQueryResult('SELECT ?s WHERE { ?s ?p ?o }', function (err, pic) {
// Node convention
if(err) {
return container.showError(err);
}
container.render(pic);
});
// Streams are EventEmitters
dataStream.on('data', function(data) {
// Consume data chunk
});
dataStream.on('error', function(err) {
// Handle errors
});
dataStream.on('end', function() {
// No more data, stream ended
});
// With a pipe method
dataStream.pipe(compressor('zip')).pipe(res);
Want to know more? Stream Handbook
Event-stream project
var es = require('event-stream');
var domstream = require('domnode-dom');
var queryStream = es.pipeline(
domstream.createReadStream('input.query', 'keyup'),
es.mapSync(trim),
es.mapSync(toLowerCase),
es.mapSync(function(text) {
container.showProgressIndicator();
return text;
}),
es.map(getQueryResult),
);
queryStream.on('data', container.render.bind(container));
queryStream.on('error', container.error.bind(container));
queryStream.on('end', container.hideProgressIndicator.bind(container));
var queryText = $('input[type="text"][name="query"]')
.asEventStream('keyup')
.map(".target.value")
.map(trimText)
.toProperty(""); // memory !
queryText
.sample(500)
.skipDuplicates()
.filter(shorterThan(3))
.map(getQueryResult)
.onValue(function (res) {
queryText.on('data', container.appendResult.bind(container));
queryText.on('end', container.end.bind(container));
});
Use the most simple tool that can solve your problem.