Below is a snapshot of my code from routes/index.js
exports.index = function(req, res){
var results=new Array();
for(var i=0; i<1000;i++){
//do database query or time intensive task here based on i
// add each result to the results array
}
res.render('index', { title: 'Home !' , results:results });
};
If I run this code , due to the asynchronous nature of javascript the last line gets executed before the loop gets pletely processed . Hence my webpage doesnt have the results . How do I structure this such a way that the page gets loaded once the queries are pleted ?
Updated
Inside the loop I have database code ( Redis ) like the below -
client.hgetall("game:" +i, function(err, reply) {
results.push(reply.name);
});
Below is a snapshot of my code from routes/index.js
exports.index = function(req, res){
var results=new Array();
for(var i=0; i<1000;i++){
//do database query or time intensive task here based on i
// add each result to the results array
}
res.render('index', { title: 'Home !' , results:results });
};
If I run this code , due to the asynchronous nature of javascript the last line gets executed before the loop gets pletely processed . Hence my webpage doesnt have the results . How do I structure this such a way that the page gets loaded once the queries are pleted ?
Updated
Inside the loop I have database code ( Redis ) like the below -
client.hgetall("game:" +i, function(err, reply) {
results.push(reply.name);
});
Share
Improve this question
edited Dec 22, 2012 at 13:51
geeky_monster
asked Dec 17, 2012 at 2:15
geeky_monstergeeky_monster
8,82218 gold badges58 silver badges87 bronze badges
2
- 1 What exactly is in the loop body? Does it support callbacks? – zerkms Commented Dec 17, 2012 at 2:21
- hi zerkms - I just updated the question to add details about that part as well . Yes it supports callbacks. – geeky_monster Commented Dec 17, 2012 at 2:56
2 Answers
Reset to default 6Use the async library:
exports.index = function(req, res){
var results=new Array();
async.forEach(someArray, function(item, callback){
// call this callback when any asynchronous processing is done and
// this iteration of the loop can be considered plete
callback();
// function to run after loop has pleted
}, function(err) {
if ( !err) res.render('index', { title: 'Home !' , results:results });
});
};
If one of the tasks inside the loop is asynchronous, you need to pass the asynchronous task a callback that calls callback()
. If you don't have an array to use in forEach
, just populate one with integers 1-1000.
Edit: Given your latest code, just put the async
callback()
right after responses.push(reply.name)
.
exports.index = function(req, res) {
var events = require("events");
var e = new events.EventEmitter();
e.expected = 1000;
e.finished = 0;
e.results = [];
e.on("finishedQuery", (function(err, r) {
this.finished += 1;
this.results.push(r && r.name);
if (this.finished === this.expected) {
res.render('index', { title: 'Home !' , results:this.results });
};
}).bind(e));
for (var i = 0; i < e.expected; i++) {
client.hgetall("game:" + i, function(err, reply) {
e.emit("finishedQuery", err, reply);
});
};
};
Of course, the above code doesn't handle [1 or more] errors. You'd need to add logic that only responds (1) on the first error or (2) if no errors occur.