0

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;
}
4
  • 1
    The problem is i > rows.length by the time the query completes Commented Sep 15, 2015 at 18:53
  • What do you mean? How would that happen? Commented Sep 15, 2015 at 18:54
  • i == rows.length actually Commented Sep 15, 2015 at 18:54
  • 1
    If you used let i instead of var i in 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 use theArray.forEach, do it. Commented Sep 15, 2015 at 18:54

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

10 Comments

So how would I return issues once it has all the info?
You wouldn't, as that isn't possible. instead, you would need to return either a promise, or have the function accept a callback.
Then I'm not sure I can wrap my head around replacing that logic. hmm. I guess I'll have to look further. I'll try the forEach though.
This is what I ended up having to do. Can you please look over this and tell me if this is even close to idiomatic. I am very new to Javascript and am coming from Java, so it's a huge change. gist.github.com/Connorelsea/2da2f8c96740eda0f788
Here's what it might look like using promises: gist.github.com/tentonaxe/5dd43c25d206ad480e22 (based on the gist 6 comments up)
|
0

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
        }
    )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.