Before going into the query, the issues object is defined, inside of the issues query it is undefined. I tried a solution mentioned on posts of the same type, but it did not work. Comments in the code explain the issue further.
var createIssues = function createIssues(rows, wrap) {
var issues = [];
for (var i = 0; i < rows.length; i++) {
// Processing code redacted
issues.push({
id : rows[i].id,
// Other field redacted
});
// ISSUES OBJECT CORRECT HERE
console.log(JSON.stringify(issues[i]))
// Query comments for individual post
connection.query(
"SELECT C.id, C.elementID, C.googleID, C.time, C.body FROM comments C WHERE elementID = ? AND approved = 1", issues[i].id,
function (err, rows_comments) {
// ISSUES OBJECT UNDEFINED HERE
console.log(JSON.stringify(issues[i]))
// More code redacted
}
)
}
return issues;
}
I tried passing it in as a function, similar to how I found in explanations online, but now it is saying "TypeError: undefined is not a function"
var createIssues = function createIssues(rows, wrap) {
var issues = []; // Create issues array
// Loop throug every issue that was
// returned by the SQL query.
for (var i = 0; i < rows.length; i++) {
// Redacted processing code
issues.push({
id : rows[i].id,
// Redacted extra fields
});
(function(issues) {
connection.query(
"SELECT C.id, C.elementID, C.googleID, C.time, C.body FROM comments C WHERE elementID = ? AND approved = 1", issues[i].id,
function (err, rows_comments) {
// Can't access issues here, undefined
}
)
})(issues);
}
return issues;
}
2 Answers 2
The problem here is you passed the whole issues array into your iife rather than only the individual one, thus making the iife pointless because it doesn't solve the problem it is meant to solve.
(function(issue) {
connection.query(
"SELECT C.id, C.elementID, C.googleID, C.time, C.body FROM comments C WHERE elementID = ? AND approved = 1", issue.id,
function (err, rows_comments) {
// worky
}
)
})(issues[i]);
That said, you can completely avoid this problem by using the forEach method that is available to all arrays. If you have an array, and you need to loop over it with a step of 1, there's no reason not to use an array method rather than a for loop.
var createIssues = function createIssues(rows, wrap) {
var issues = []; // Create issues array
// Loop throug every issue that was
// returned by the SQL query.
rows.forEach(function (row, index) {
// Redacted processing code
var issue = {
id : row.id,
// Redacted extra fields
}
issues.push(issue);
connection.query(
"SELECT C.id, C.elementID, C.googleID, C.time, C.body FROM comments C WHERE elementID = ? AND approved = 1", issue.id,
function (err, rows_comments) {
// worky
}
)
});
return issues;
}
Please note however that issues is going to be returned to the calling scope before all of the asynchronous work is complete, meaning anything you do in place of the // worky comment will not take affect until some time later.
10 Comments
I think you're still going to have issues when you return the issues object because you are modifying it asynchronously. For this question you don't have access to i in your query callback BUT the row you are returning has the same id which should suffice for lookup:
connection.query(
"SELECT C.id, C.elementID, C.googleID, C.time, C.body FROM comments C WHERE elementID = ? AND approved = 1", issues[i].id,
function (err, rows_comments) {
// ISSUES OBJECT UNDEFINED HERE
// console.log(JSON.stringify(issues[i])) //i is not what you expect here
console.log(JSON.stringify(issues[row_comments.id])); //the ID comes back in the query
// More code redacted
}
)
i > rows.lengthby the time the query completesi == rows.lengthactuallylet iinstead ofvar iin your for loop, it would work. but that requires using either node.js 4 or the --harmony flag. using Array.prototype.forEach instead of a for loop to loop over an array would also solve it. Good programming practices are good practices because they avoid problems. If you can usetheArray.forEach, do it.