Denis Evseev Denis Evseev - 11 days ago 5
Javascript Question

How to pass rows to inner multiple requests

I have a request which obtains rows of questions

con.query('select * from questions where `quizId` = ? ', quizId, function(err, rows)


then I need to get answers to each question.

for(var i=0; i < rows.length; i++){
answer.getAllByQuestionId(rows[i].id, function(err, data){


I get answers and questions without any troubles. But I can't add the answers into each question since
rows[i] is undefined


Here is the whole method:

this.getAllByQuizId = function(quizId, callback) {
connection.acquire(function(err, con) {
con.query('select * from questions where `quizId` = ? ', quizId, function(err, rows) {
if (err) callback(err);
completed_requests = 0;

for(var i=0; i < rows.length; i++){
answer.getAllByQuestionId(rows[i].id, function(err, data, rows){

rows[i].answers = data;
completed_requests++;

if (completed_requests == rows.length - 1) {
callback(null, rows);
}
});
}
});
});
}

Answer

The reason is, the i value in the for loop get changed on each iteration whereas the function answer.getAllByQuestionId is asynchronous and when the callback is getting called for each iteration the i value will be different basically outside of the bounds. And also, the callback of the function answer.getAllByQuestionId should have only two arguments and not three as you did.

The easiest fix is, you can use rows.forEach instead of for loop to handle this as below. Otherwise you can go with promise modules like async, bluebird etc.

this.getAllByQuizId = function(quizId, callback) {
    connection.acquire(function(err, con) {
      con.query('select * from questions where `quizId` = ? ', quizId, function(err, rows) {
        if (err) callback(err); 
        completed_requests = 0;


            rows.forEach(function(row){ 
               answer.getAllByQuestionId(row.id, function(err, data){

                    row.answers = data;
                    completed_requests++;

                    if (completed_requests == rows.length - 1) {
                        callback(null, rows);
                    }
                });
            });                             
        });    
    });
}