I'm converting an api server from a plain nodejs script to one using the express framework for much better stability.
One of my problems is the fact that you can't return values from a callback because the original code has continued...
var _json = api.query();
Somehow, we'd prefer the .query() return the final results object, so we can stringify it to JSON, then pass it to the render enging like so:
// Render the display
res.render('posts-resp', {
title: res.app.settings.app_title,
_use_Callback: _use_Callback,
json: _json
});
However, the db query uses callbacks to handle the query results so it's impossible to return a value like this. In the original version, the db script handled rendering the final view, but I don't want them tied together like that.
query: function(){
db.query( this._buildQuery(), function(err, res){
if(err){ throw err; }
res.fetchAll(function(err, rows){
if(err){ throw err; }
db.query('SELECT FOUND_ROWS() as num, UNIX_TIMESTAMP() as query_timestamp;', function(err, cnt_res){
if(err){ throw err; }
cnt_res.fetchAll(function(err, cnt_rows){
var obj = {
results:rows,
total_results:cnt_rows[0].num,
current_offset:self.offset,
query_timestamp:cnt_rows[0].query_timestamp
};
// ... ?
});
});
});
});
}
How can I properly get the data and pass them to the render system?
JavaScript is a pretty flexible language. You don't really need to directly tie your view to the DB code since you can use a function as a wrapper to abstract away the view code and keep it separate from the DB logic.
Callbacks can be a very powerful tool when asynchronous logic is required. I'm not sure if it's required here or not, but you can still keep the view code separate from the DB code using the wrapper function to encapsulate the view logic:
Function wrapper around view code:
function delegateToView(data) {
// process data here before sending to view
// Render the display
res.render('posts-resp', {
title: res.app.settings.app_title,
_use_Callback: _use_Callback,
json: _json
});
}
DB Code with function call in callback:
db.query('SELECT FOUND_ROWS() as num, UNIX_TIMESTAMP() as query_timestamp;', function(err, cnt_res){
if(err){ throw err; }
cnt_res.fetchAll(function(err, cnt_rows){
var obj = {
results:rows,
total_results:cnt_rows[0].num,
current_offset:self.offset,
query_timestamp:cnt_rows[0].query_timestamp
};
// ... ?
//call your delegator here and pass in any needed data.
// this keeps the actual view code separate.
delegateToView(obj);
});
});
Now if your view code ever needs to change, you don't need to touch any of the logic in the DB code or any of the logic in the callback function. Good luck!