3

I have this snippet that counts the number rows and returns the number of rows found in a MySQL table. This is the code, in which I have used underscore.js's _.each to iterate.

var all_rows = Noder.query('SELECT count(*) as erow from crud ', function(err, the_rows) {

            _.each(the_rows, function (corndog) {
            var trows = corndog.erow;
            console.log("All rows", trows);
            });

            // var das_rows = trows;
            // var total_pages = Math.ceil(das_rows / per_page);
            // console.log("Pages",total_pages);

         res.view('noder/orm', {
            layout: 'layout',
            js:the_rows,
            post:results,
            title: 'This is the hi page title. Gandalf The great.'
        });
        });

I want to use trows to calculate the number of pages are to be created for my paging code. However, I cannot access the variable trows.

This is the output of console.log(the_rows);

[ RowDataPacket { erow: 12 } ]

Is there another way I can do this to make trows available to the rest of my code?

underscore_d
  • 6,309
  • 3
  • 38
  • 64
Le Qs
  • 785
  • 2
  • 9
  • 26

4 Answers4

6

The issue is that var trows only exists inside of the iterator, as that function creates its own scope to contain variables.

function (corndog) {
    var trows = corndog.erow;
    console.log("All rows",trows);
} // `trows` is removed from existence at this point

console.log(trows); // ReferencError

But, the function does have access to variables in surrounding scopes. So, you can declare trows outside of the function, then assign it inside.

var trows;

_.each(the_rows, function (corndog) {
    trows = corndog.erow; // note removal of `var`
    console.log("All rows",trows);
});

console.log(trows); // 12

Though, _.each() isn't really necessary when you're only wanting a single value. You can access a particular index of the collection and chain onto that the property you're after:

var trows = the_rows[0].erow;

If there's concern about the_rows being empty, you can test for that to avoid errors with undefined:

var trows = the_rows.length ? the_rows[0].erow : null;

Side note: Be sure to always test for an err. If one occurs, the_rows will likely be null or undefined.

Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
1

I may not understand what you're asking - but

var allTrows = [];
_.each(the_rows, function (corndog) {
        var trows = corndog.erow;
        console.log("All rows",trows);
         allTrows.push (trows);
});

Then return allTrows in your res.render.

Tim
  • 539
  • 2
  • 9
1

While Jonathan and Ilya have already given practical solutions to your specific problem, let me provide a generic answer to the question in the title:

The simplest way to replace _.each() is to iterate over the array using a plain for loop:

for (var i = 0; i < the_rows.length; i++) {
    var row = the_rows[i];
    console.log( "In loop: row = the_rows[" + i + "] =", row );
}
console.log( "After loop: row =", row );

or, in ES6 or later, a for...of loop:

for (var row of the_rows) {
    console.log( "In loop: row =", row );
}
console.log( "After loop: row =", row );

(You could also use a for...in loop, but you probably shouldn't.)

Since these are built-in looping constructs, and do not involve an inner function like _.each() does, any variables defined in them will retain their last value after the loop ends.


Another way to replace _.each is using the built-in .forEach() method of JS arrays:

the_rows.forEach( function (row, i) {
    console.log( "In loop: row = the_rows[" + i + "] =", row );
} );

or, if you want to use this method to loop over something that looks like an array but isn't actually one (such as, say, a DOM NodeList):

Array.prototype.forEach.call( the_rows, function (row, i) {
    console.log( "In loop: row = the_rows[" + i + "] =", row );
} );

However, since .forEach() does require wrapping the loop body in an inner function, just like _.each(), any variables declared using var inside it will not be available outside the loop. However, variables declared outside the loop function are visible inside in it, so you can do e.g. this:

var last_row;
the_rows.forEach( function (row, i) {
    last_row = row;  // <-- no "var"!
    console.log( "In loop: last_row = row = the_rows[" + i + "] =", row );
} );
console.log( "After loop: last_row =", last_row );
Community
  • 1
  • 1
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
0

Declare trows outside of the loop:

var trows = 0;
_.each(the_rows, function (corndog) {
    trows += corndog.erow;
    console.log("All rows",trows);
});
Ilya
  • 5,377
  • 2
  • 18
  • 33